Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unary minus on 'numeric' inputs like '-1' #9443

Closed
p5pRT opened this issue Aug 7, 2008 · 10 comments
Closed

Unary minus on 'numeric' inputs like '-1' #9443

p5pRT opened this issue Aug 7, 2008 · 10 comments

Comments

@p5pRT
Copy link

p5pRT commented Aug 7, 2008

Migrated from rt.perl.org#57706 (status was 'resolved')

Searchable as RT57706$

@p5pRT
Copy link
Author

p5pRT commented Aug 7, 2008

From @epa

Created by @epa

This was a bit surprising​:

% perl -E 'say -"-1"'
+1
% perl -E 'say - -1'
1
% perl -E 'say 0 - "-1"'
1

On checking perlop it says​:

  Unary "-" performs arithmetic negation if the operand is 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.

That makes some sense, then, but what is the meaning of 'numeric'?

I had expected that reading the string '-1' from standard input and
then chomping it would give something numeric, to which normal
arithmetic would apply. But in fact you need to do something like
'$x += 0' to coerce it to a number first. This seems unperlish.

Perhaps the word 'numeric' in this manual page has a clearly defined
meaning which I am unaware of, but if not, could the semantics be
changed a little bit so that a string such as '-1' is considered to be
'numeric' and so arithmetically negated by the unary - operator?

I would expect to see

% perl -E 'say - -1'
1
% perl -E 'say -"-1"'
1
% perl -E 'say -"-foo"'
+foo

To me, that matches the documentation better than the current behaviour.

Perl Info

Flags:
    category=core
    severity=medium

This perlbug was built using Perl 5.10.0 in the Fedora build system.
It is being executed now by Perl 5.10.0 - Mon Jul 21 06:53:59 EDT 2008.

Site configuration information for perl 5.10.0:

Configured by Red Hat, Inc. at Mon Jul 21 06:53:59 EDT 2008.

Summary of my perl5 (revision 5 version 10 subversion 0) configuration:
  Platform:
    osname=linux, osvers=2.6.18-92.1.6.el5, archname=i386-linux-thread-multi
    uname='linux x86-7 2.6.18-92.1.6.el5 #1 smp fri jun 20 02:36:06 edt 2008 i686 i686 i386 gnulinux '
    config_args='-des -Doptimize=-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-s\
ize=4 -m32 -march=i386 -mtune=generic -fasynchronous-unwind-tables -DPERL_USE_SAFE_PUTENV -Dversion=5.10.0 -Dmyhostname=localho\
st -Dperladmin=root@localhost -Dcc=gcc -Dcf_by=Red Hat, Inc. -Dinstallprefix=/usr -Dprefix=/usr -Dprivlib=/usr/lib/perl5/5.10.0\
 -Dsitelib=/usr/local/lib/perl5/site_perl/5.10.0 -Dvendorlib=/usr/lib/perl5/vendor_perl/5.10.0 -Darchlib=/usr/lib/perl5/5.10.0/\
i386-linux-thread-multi -Dsitearch=/usr/local/lib/perl5/site_perl/5.10.0/i386-linux-thread-multi -Dvendorarch=/usr/lib/perl5/ve\
ndor_perl/5.10.0/i386-linux-thread-multi -Darchname=i386-linux-thread-multi -Dotherlibdirs=/usr/lib/perl5/site_perl/5.10.0 -Dve\
ndorprefix=/usr -Dsiteprefix=/usr/local -Duseshrplib -Dusethreads -Duseithreads -Duselargefiles -Dd_dosuid -Dd_semctl_semun -Di\
_db -Ui_ndbm -Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Duseperlio -Dinstallusrbinperl=n -Ubincompat5005 -Uversiononly -Dpag\
er=/usr/bin/less -isr -Dd_gethostent_r_proto -Ud_endhostent_r_proto -Ud_sethostent_r_proto -Ud_endprotoent_r_proto -Ud_setproto\
ent_r_proto -Ud_endservent_r_proto -Ud_setservent_r_proto -Dscriptdir=/usr/bin'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=define, usemultiplicity=define
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=undef, use64bitall=undef, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='gcc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DDEBUGGING -fno-strict-aliasing -pipe -I/usr/local/include -D_LARGEFILE_SOU\
RCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm',
    optimize='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i\
386 -mtune=generic -fasynchronous-unwind-tables -DPERL_USE_SAFE_PUTENV',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -DDEBUGGING -fno-strict-aliasing -pipe -I/usr/local/include -I/usr/include/gdbm'
    ccversion='', gccversion='4.3.0 20080428 (Red Hat 4.3.0-8)', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=4, prototype=define
  Linker and Libraries:
    ld='gcc', ldflags =' -L/usr/local/lib'
    libpth=/usr/local/lib /lib /usr/lib
    libs=-lresolv -lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lpthread -lc
    perllibs=-lresolv -lnsl -ldl -lm -lcrypt -lutil -lpthread -lc
    libc=/lib/libc-2.8.so, so=so, useshrplib=true, libperl=libperl.so
    gnulibc_version='2.8'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E -Wl,-rpath,/usr/lib/perl5/5.10.0/i386-linux-thread-multi/C\
ORE'
    cccdlflags='-fPIC', lddlflags='-shared -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ss\
p-buffer-size=4 -m32 -march=i386 -mtune=generic -fasynchronous-unwind-tables -DPERL_USE_SAFE_PUTENV -L/usr/local/lib'

Locally applied patches:



@INC for perl 5.10.0:
    /home/eda/lib/perl5/5.10.0/i386-linux-thread-multi
    /home/eda/lib/perl5/5.10.0
    /home/eda/lib/perl5/site_perl/5.10.0/i386-linux-thread-multi
    /home/eda/lib/perl5/site_perl/5.10.0
    /usr/local/lib/perl5/site_perl/5.10.0/i386-linux-thread-multi
    /usr/local/lib/perl5/site_perl/5.10.0/i386-linux-thread-multi
    /usr/local/lib/perl5/site_perl/5.10.0
    /usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi
    /usr/lib/perl5/vendor_perl/5.10.0/5.10.0/i386-linux-thread-multi
    /usr/lib/perl5/vendor_perl/5.10.0/5.10.0
    /usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi
    /usr/lib/perl5/vendor_perl/5.10.0
    /usr/lib/perl5/5.10.0/i386-linux-thread-multi
    /usr/lib/perl5/5.10.0
    /usr/local/lib/perl5/site_perl/5.10.0/i386-linux-thread-multi
    /usr/local/lib/perl5/site_perl/5.10.0
    /usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi
    /usr/lib/perl5/vendor_perl/5.10.0
    /usr/lib/perl5/vendor_perl
    /usr/lib/perl5/site_perl/5.10.0/5.10.0/i386-linux-thread-multi
    /usr/lib/perl5/site_perl/5.10.0/5.10.0
    /usr/lib/perl5/site_perl/5.10.0/i386-linux-thread-multi
    /usr/lib/perl5/site_perl/5.10.0
    .


Environment for perl 5.10.0:
    HOME=/home/eda
    LANG=en_GB.UTF-8
    LANGUAGE (unset)
    LC_COLLATE=C
    LC_CTYPE=en_GB.UTF-8
    LC_MESSAGES=en_GB.UTF-8
    LC_MONETARY=en_GB.UTF-8
    LC_NUMERIC=en_GB.UTF-8
    LC_TIME=en_GB.UTF-8
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/eda/bin:/usr/lib/qt-3.3/bin:/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin
    PERL5LIB=/home/eda/lib/perl5/5.10.0:/home/eda/lib/perl5/site_perl/5.10.0:/usr/local/lib/perl5/site_perl/5.10.0/i386-linux-thread-multi:/usr/local/lib/perl5/site_perl/5.10.0:/usr/lib/perl5/vendor_perl/5.10.0/i386-linux-thread-multi:/usr/lib/perl5/vendor_perl/5.10.0
    PERL_BADLANG (unset)
    SHELL=/bin/bash

-- 
Ed Avis <eda@waniasset.com>

______________________________________________________________________
This email has been scanned by the MessageLabs Email Security System.
For more information please visit http://www.messagelabs.com/email 
______________________________________________________________________

@p5pRT
Copy link
Author

p5pRT commented Nov 10, 2008

From renee.baecker@smart-websolutions.de

Hi,

% perl -E 'say -"-1"'
+1
% perl -E 'say - -1'
1
% perl -E 'say 0 - "-1"'
1

[...]

I would expect to see

% perl -E 'say - -1'
1
% perl -E 'say -"-1"'
1
% perl -E 'say -"-foo"'
+foo

To me, that matches the documentation better than the current
behaviour.

The documentation is a bit inconsistent​:

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

Your first example is a string. So the current behaviour seems to be
correct.

OTOH, perlnumber says "The binary operators + - * / % == != > < >=
<= and the unary operators - abs and -- will attempt to convert
arguments to integers"

...

The attached patch adds the conversion if the value of the SV
looks_like_number...

Nevertheless, the documentation should be fixed, no matter what
behaviour is "correct".

See also the discussion in #36675
(http​://rt.perl.org/rt3/Public/Bug/Display.html?id=36675)

Cheers,
Renée

@p5pRT
Copy link
Author

p5pRT commented Nov 10, 2008

From renee.baecker@smart-websolutions.de

57706.patch
--- pp.c.orig	2008-11-10 16:17:24.584644839 +0100
+++ pp.c	2008-11-10 15:57:47.053094661 +0100
@@ -2398,6 +2398,11 @@
 	SV * const sv = sv_2num(TOPs);
 	const int flags = SvFLAGS(sv);
 	SvGETMAGIC(sv);
+
+        if( looks_like_number( sv ) ){
+           SvIV_please( sv );
+        }   
+
 	if ((flags & SVf_IOK) || ((flags & (SVp_IOK | SVp_NOK)) == SVp_IOK)) {
 	    /* It's publicly an integer, or privately an integer-not-float */
 	oops_its_an_int:
--- t/op/negate.t.orig	2008-11-10 16:12:23.035094284 +0100
+++ t/op/negate.t	2008-11-10 16:16:42.186535842 +0100
@@ -18,8 +18,8 @@
 is(-"10", -10, "Negation of a positive string to negative");
 is(-"10.0", -10, "Negation of a positive decimal sting to negative");
 is(-"10foo", -10, "Negation of a numeric-lead string returns negation of numeric");
-is(-"-10", "+10", 'Negation of string starting with "-" returns a string starting with "+" - numeric');
-is(-"-10.0", "+10.0", 'Negation of string starting with "-" returns a string starting with "+" - decimal');
+is(-"-10", 10, 'Negation of string starting with "-" returns a string starting with "+" - numeric');
+is(-"-10.0", 10.0, 'Negation of string starting with "-" returns a string starting with "+" - decimal');
 is(-"-10foo", "+10foo", 'Negation of string starting with "-" returns a string starting with "+" - non-numeric');
 is(-"xyz", "-xyz", 'Negation of a negative string adds "-" to the front');
 is(-"-xyz", "+xyz", "Negation of a negative string to positive");

@p5pRT
Copy link
Author

p5pRT commented Nov 10, 2008

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Oct 4, 2010

From @obra

On Sun 26.Sep'10 at 14​:18​:48 -0700, Father Chrysostomos wrote​:

There is a patch attached to that ticket that changes - "-1" to return 1 instead of "+1". I think this is a very good idea, but it is a backward-incompatible change, so I think it needs your explicit approval first.

And now you have it. I support the change.

Thanks!

-j

@p5pRT
Copy link
Author

p5pRT commented Oct 4, 2010

From @cpansprout

On Mon Nov 10 07​:34​:21 2008, renee.baecker@​smart-websolutions.de wrote​:

Hi,

% perl -E 'say -"-1"'
+1
% perl -E 'say - -1'
1
% perl -E 'say 0 - "-1"'
1

[...]

I would expect to see

% perl -E 'say - -1'
1
% perl -E 'say -"-1"'
1
% perl -E 'say -"-foo"'
+foo

To me, that matches the documentation better than the current
behaviour.

The documentation is a bit inconsistent​:

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

Your first example is a string. So the current behaviour seems to be
correct.

OTOH, perlnumber says "The binary operators + - * / % == != > < >=
<= and the unary operators - abs and -- will attempt to convert
arguments to integers"

...

The attached patch adds the conversion if the value of the SV
looks_like_number...

Thank you. Applied as a5b9289.

Nevertheless, the documentation should be fixed, no matter what
behaviour is "correct".

I tweaked the perlop description in commit da2f94c.

@p5pRT
Copy link
Author

p5pRT commented Oct 4, 2010

From [Unknown Contact. See original ticket]

On Mon Nov 10 07​:34​:21 2008, renee.baecker@​smart-websolutions.de wrote​:

Hi,

% perl -E 'say -"-1"'
+1
% perl -E 'say - -1'
1
% perl -E 'say 0 - "-1"'
1

[...]

I would expect to see

% perl -E 'say - -1'
1
% perl -E 'say -"-1"'
1
% perl -E 'say -"-foo"'
+foo

To me, that matches the documentation better than the current
behaviour.

The documentation is a bit inconsistent​:

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

Your first example is a string. So the current behaviour seems to be
correct.

OTOH, perlnumber says "The binary operators + - * / % == != > < >=
<= and the unary operators - abs and -- will attempt to convert
arguments to integers"

...

The attached patch adds the conversion if the value of the SV
looks_like_number...

Thank you. Applied as a5b9289.

Nevertheless, the documentation should be fixed, no matter what
behaviour is "correct".

I tweaked the perlop description in commit da2f94c.

@p5pRT
Copy link
Author

p5pRT commented Oct 4, 2010

@cpansprout - Status changed from 'open' to 'resolved'

@p5pRT p5pRT closed this as completed Oct 4, 2010
@p5pRT
Copy link
Author

p5pRT commented Jun 7, 2012

From @cpansprout

On Mon Oct 04 08​:43​:03 2010, sprout wrote​:

On Mon Nov 10 07​:34​:21 2008, renee.baecker@​smart-websolutions.de wrote​:

Hi,

% perl -E 'say -"-1"'
+1
% perl -E 'say - -1'
1
% perl -E 'say 0 - "-1"'
1

[...]

I would expect to see

% perl -E 'say - -1'
1
% perl -E 'say -"-1"'
1
% perl -E 'say -"-foo"'
+foo

To me, that matches the documentation better than the current
behaviour.

The documentation is a bit inconsistent​:

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

Your first example is a string. So the current behaviour seems to be
correct.

OTOH, perlnumber says "The binary operators + - * / % == != > < >=
<= and the unary operators - abs and -- will attempt to convert
arguments to integers"

...

The attached patch adds the conversion if the value of the SV
looks_like_number...

Thank you. Applied as a5b9289.

Except that patch did not take magic variables into account.

However, no numeric ops fully accounted for those.

This is now fixed for magic variables in e38171c, which relies on
changes made in 01f91bf, two commits earlier.

Nevertheless, the documentation should be fixed, no matter what
behaviour is "correct".

I tweaked the perlop description in commit da2f94c.

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Jun 7, 2012

From [Unknown Contact. See original ticket]

On Mon Oct 04 08​:43​:03 2010, sprout wrote​:

On Mon Nov 10 07​:34​:21 2008, renee.baecker@​smart-websolutions.de wrote​:

Hi,

% perl -E 'say -"-1"'
+1
% perl -E 'say - -1'
1
% perl -E 'say 0 - "-1"'
1

[...]

I would expect to see

% perl -E 'say - -1'
1
% perl -E 'say -"-1"'
1
% perl -E 'say -"-foo"'
+foo

To me, that matches the documentation better than the current
behaviour.

The documentation is a bit inconsistent​:

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

Your first example is a string. So the current behaviour seems to be
correct.

OTOH, perlnumber says "The binary operators + - * / % == != > < >=
<= and the unary operators - abs and -- will attempt to convert
arguments to integers"

...

The attached patch adds the conversion if the value of the SV
looks_like_number...

Thank you. Applied as a5b9289.

Except that patch did not take magic variables into account.

However, no numeric ops fully accounted for those.

This is now fixed for magic variables in e38171c, which relies on
changes made in 01f91bf, two commits earlier.

Nevertheless, the documentation should be fixed, no matter what
behaviour is "correct".

I tweaked the perlop description in commit da2f94c.

--

Father Chrysostomos

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant