++n
and
--n
fail silently for numeric-valued n.
Given that C-style for-loops are relatively infrequent in Python and
are usually written using range() when they are needed, it's probably
not that prevalent a problem.
I suppose the lexer could be changed to make ++ and -- illegal...
Cheers,
Chris
--
http://blog.rebertia.com
What do you mean, "fail silently"? They do exactly what you should expect:
>>> ++5 # positive of a positive number is positive
5
>>> --5 # negative of a negative number is positive
5
>>> -+5 # negative of a positive number is negative
-5
So does the bitwise-not unary operator:
>>> ~~5
5
I'm not sure what "bug" you're seeing. Perhaps it's your expectations
that are buggy, not Python.
--
Steven
Well, those expectations are taken seriously when new features are
introduced into the language - and sometimes the feature is dismissed just
because it would be confusing for some.
If a += 1 works, expecting ++a to have the same meaning is very reasonable
(for those coming from languages with a ++ operator, like C or Java) -
more when ++a is a perfectly valid expression.
If this issue isn't listed under the various "Python gotchas" articles, it
should...
--
Gabriel Genellina
Well sure, it's not unreasonable to expect ++n and --n to behave as in
other languages, and since they don't, perhaps they should be listed as
a "Python gotcha".
But even so, it's quite arrogant of the OP to flaunt his ignorance of
the language by claiming this is a bug and a failure. It shouldn't have
been all that hard for him to figure out what was really happening.
Gary Herron
That depends on what you call a "bug". In his classical book "The art of
software testing", Myers says that a program has a bug when it doesn't
perform as the user expects reasonably it to do (not an exact quote, I
don't have the book at hand). That's a lot broader than developers like to
accept.
In this case, a note in the documentation warning about the potential
confusion would be fine.
--
Gabriel Genellina
[... re confusion over ++n etc ...]
> In this case, a note in the documentation warning about the potential
> confusion would be fine.
The difficulty here is knowing where to put such a warning.
You obviously can't put it against the "++" operator as such
because... there isn't one. You could put it against the unary
plus operator, but who's going to look there? :)
I've wondered for a while whether it wouldn't be a good move
to include the official (or any other) Python FAQ into the
standard docs set. If we did, that would be the obvious place
for this piece of documentation, seems to me.
TJG
> The difficulty here is knowing where to put such a warning.
> You obviously can't put it against the "++" operator as such
> because... there isn't one.
This bug is an epiphenomenon. :)
The problem is: where do you stop? If you're going to add something to
the documentation to address every expectation someone might hold
coming from another language, the docs are going to get pretty big.
I think a language should be intuitive within itself, but not be
required to be intuitable based on _other_ languages (unless, of
course, that's an objective of the language). If I expect something in
language-A to operate the same way as completely-unrelated-language-B,
I'd see that as a failing on my behalf, especially if I hadn't read
language-A's documentation first. I'm not adverse to one language
being _explained_ in terms of another, but would much prefer to see
those relegated to "Python for <x> programmers" articles rather than
in the main docs themselves.
Well, like I suggested, it /could/ be made an operator (or rather, a
lexer token) which just causes a compile/parse error.
What fail? In Python, ++n and --n are fatuous expressions which
SUCCEED silently except for rare circiumstances e.g. --n will cause an
overflow exception on older CPython versions if isinstance(n, int) and
n == -sys.maxint - 1.
How would that help someone who does not read the doc?
> En Mon, 06 Jul 2009 00:28:43 -0300, Steven D'Aprano
> <st...@remove-this-cybersource.com.au> escribió:
>> On Mon, 06 Jul 2009 14:32:46 +1200, Lawrence D'Oliveiro wrote:
>>
>>> I wonder how many people have been tripped up by the fact that
>>>
>>> ++n
>>>
>>> and
>>>
>>> --n
>>>
>>> fail silently for numeric-valued n.
>>
>> What do you mean, "fail silently"? They do exactly what you should
>> expect:
>>>>> ++5 # positive of a positive number is positive
>>
>> I'm not sure what "bug" you're seeing. Perhaps it's your expectations
>> that are buggy, not Python.
>
> Well, those expectations are taken seriously when new features are
> introduced into the language - and sometimes the feature is dismissed
> just because it would be confusing for some. If a += 1 works, expecting
> ++a to have the same meaning is very reasonable (for those coming from
> languages with a ++ operator, like C or Java) - more when ++a is a
> perfectly valid expression. If this issue isn't listed under the various
> "Python gotchas" articles, it should...
The fact that it isn't suggests strongly to me that it isn't that common
a surprise even for Java and C programmers. This is the first time I've
seen anyone raise it as an issue.
There are plenty of other languages other than Java and C. If we start
listing every feature of Python that's different from some other
language, we'll never end.
For what it's worth, Ruby appears to behave the same as Python:
$ irb
irb(main):001:0> n = 5
=> 5
irb(main):002:0> ++n
=> 5
irb(main):003:0> --n
=> 5
irb(main):004:0> -+n
=> -5
--
Steven
It obviously won't.
All it will do, is that it will enable people on this group,
who may read the manual, to tell people who complain,
to RTFM.
I agree that it would be a good idea to make it an
error, or a warning - "this might not do what you
think it does", or an "are you sure?" exception.
:-)
- Hendrik
I dunno. Specifically recognizing (and emitting code code for) a token
that's not actually part of the language because people coming from
other languages think it exists seems like the start of a fustercluck.
Recent python-ideas discussion on this subject:
http://mail.python.org/pipermail/python-ideas/2009-March/003741.html
Mark
Indeed, arguably it's a bug for C compilers to fail to find the valid
parsing of "++5" as "+(+5)". All I can say is that I've never even
accidentally typed that in twenty years of C programming.
--
Rhodri James *-* Wildebeest Herder to the Masses
Yes, it's their problem if they don't read the docs.
>
> I agree that it would be a good idea to make it an
> error, or a warning - "this might not do what you
> think it does", or an "are you sure?" exception.
>
> :-)
>
> - Hendrik
That would be even harder than adding a line to the docs. Besides,
the problem that Mr. alex23 pointed: "where do you stop?" would really
get out of hand.
--
Pablo Torres N.
Rather few, it seems.
> Recent python-ideas discussion on this subject:
>
> http://mail.python.org/pipermail/python-ideas/2009-March/003741.html
To add to what I wrote in that thread: it is C, not Python, that is out
of step with standard usage in math and most languages. --x = x; 1/1/x =
x; non not a = a; inverse(inverse(f)) = f; etc. And ++x= +x = x
corresponded to I(I(x)) = I(x) = x, where I is identity function.
In C as high-level assembler, the inc and dec functions are written as
-- and ++ operators for some mix of the following reasons. 1) They
correspond to machine language / assembler functions. 2) They need to be
efficient since they are used in inner loops. Function calls have
overhead. Original C did not allow inlining of function calls as best I
remember. 3) They save keystrokes; 4) 2 versions that return pre and
post change values are needed. My impression is that some opcode sets
(and hence assemblers) have only one, and efficient code requires
allowing direct access to whichever one a particular processor supports.
Basic routines can usually be written either way.
These reasons do not apply to Python or do not fit Python's style.
Anyone who spends 15 minutes skimming the chapter on expressions could
notice that 5.5. Unary arithmetic and bitwise operations has only +,-,
and ~ or that the Summary operator table at the end has no -- or ++.
Terry Jan Reedy
> Rhodri James wrote:
>> Indeed, arguably it's a bug for C compilers to fail to find the valid
>> parsing of "++5" as "+(+5)". All I can say is that I've never even
>> accidentally typed that in twenty years of C programming.
>>
> But the C language specifically defines the tokenizer as doing a
> max-match, finding the longest legal token at any point. That's how
> many things that would otherwise be ambiguous are well-defined. For
> example, if you want to divide two integers, given pointers to them, you
> need a space between the slash and the start.
> *p1/*p2 begins a comment, while *p1/ *p2 does a division
You know, I've never had that come up either! My habit of sticking spaces
around binary operators purely for legibility probably helped, but I'm
still a bit boggled.
> ... it is C, not Python, that is out of step with standard usage in math
> and most languages ...
And it is C that introduced "==" for equality, versus "=" for assignment,
which Python slavishly followed instead of keeping "=" with its mathematical
meaning and using ":=" for assignment.
Yes, there are plenty of languages other than Java and C, but the
influence of C is admittedly huge in Python. Why do you think loops
are called "for", conditionals "if" or "while", functions return via
"return", loops terminate via "break" and keep going via "continue"
and why is comparison written as "==", etc, etc? All of these are
coming from C (or an even earlier language) and my point is that users
are most of time correct when they assume that something will work the
same way as in C.
So I'd think that putting a warning in a FAQ or a Python Gotchas list
about ++n would be very useful for many users. And it does not imply
that the differences from every other language should be documented in
a similar fashion. Only C :)
Cheers,
Daniel
> For what it's worth, Ruby appears to behave the same as Python:
>
> $ irb
> irb(main):001:0> n = 5
> => 5
> irb(main):002:0> ++n
> => 5
> irb(main):003:0> --n
> => 5
> irb(main):004:0> -+n
> => -5
>
--
Psss, psss, put it down! - http://www.cafepress.com/putitdown
There are edge cases (level: very rare) where you legitimately want to
actually do that, e.g.:
class A(object):
def __init__(self, arg):
self.value = arg.value
def __pos__(self):
return B(self)
def __neg__(self):
return D(self)
class B(object):
def __init__(self, arg):
self.value = arg.value
def __pos__(self):
return C(self)
def __neg__(self):
return A(self)
class C(object):
def __init__(self, arg):
self.value = arg.value
def __pos__(self):
return D(self)
def __neg__(self):
return B(self)
class D(object):
def __init__(self, arg):
self.value = arg.value
def __pos__(self):
return A(self)
def __neg__(self):
return C(self)
def cons(val):
class E(object):
value = val
return E()
>>> a = A(cons(10))
>>> +a
<__main__.B object at 0x7fbf723c8690>
>>> ++a
<__main__.C object at 0x7fbf723c8710>
>>> +++a
<__main__.D object at 0x7fbf723c8710>
>>> --a
<__main__.C object at 0x7fbf723c8710>
> Chris Rebert wrote:
>> On Mon, Jul 6, 2009 at 1:29 AM, Lawrence
>> D'Oliveiro<l...@geek-central.gen.new_zealand> wrote:
>>> In message <mailman.2674.1246866...@python.org>, Tim
>>> Golden wrote:
>>>
>>>> The difficulty here is knowing where to put such a warning. You
>>>> obviously can't put it against the "++" operator as such because...
>>>> there isn't one.
>>> This bug is an epiphenomenon. :)
>>
>> Well, like I suggested, it /could/ be made an operator (or rather, a
>> lexer token) which just causes a compile/parse error.
>>
>> Cheers,
>> Chris
>
> There are edge cases (level: very rare) where you legitimately want to
> actually do that, e.g.:
Not so rare. Decimal uses unary plus. Don't assume +x is a no-op.
Help on method __pos__ in module decimal:
__pos__(self, context=None) unbound decimal.Decimal method
Returns a copy, unless it is a sNaN.
Rounds the number (if more then precision digits)
--
Steven
Yes, hence my comment above, ".... coming from C (or an even earlier
language) ......".
Cheers,
Daniel
Well, yes, but when would you apply it twice in a row?
(Not that I strongly support the prohibition idea, just thought it
should be brought up)
> for, if, and return were common keywords in FORTRAN.
Really? What does 'for' do in FORTRAN?
P.S. Does FORTRAN actually have keywords these days? Back when I learned it
there was no such thing as a reserved word though for all I know they may
have since added them.
--
Duncan Booth http://kupuguy.blogspot.com
Oh, really ? They would surely be wrong if they'd expect the for loop to
have any similarity with a C for loop, or - a *very* common error - if
they'd expect assignment to work the same way as in C.
> So I'd think that putting a warning in a FAQ or a Python Gotchas list
> about ++n would be very useful for many users.
Might eventually be useful, but I can't hardly recall of more than a
couple threads on this topic in 8+ years.
Mmm... Should we then claim that "the influence of FORTRAN is admittedly
huge in Python" ?-)
>> Not so rare. Decimal uses unary plus. Don't assume +x is a no-op.
[...]
> Well, yes, but when would you apply it twice in a row?
My point was that unary + isn't a no-op, and therefore neither is ++. For
Decimal, I can't think why you'd want to apply ++x, but for other
objects, who knows?
Here's a toy example:
>>> class Spam(str):
... def __pos__(self):
... return self.__class__("spam " + self)
...
>>> s = Spam("")
>>> ++++s
'spam spam spam spam '
--
Steven
C was derived from BCPL which used ":=" for assignment and "=" for
comparison.
Yes, really. I wrote ".... most of the time ....." and not "all the time".
>> So I'd think that putting a warning in a FAQ or a Python Gotchas list
>> about ++n would be very useful for many users.
>
> Might eventually be useful, but I can't hardly recall of more than a
> couple threads on this topic in 8+ years.
I'm happy we agree.
Cheers,
Daniel
Hmmmm, your comments reached a level of pedanticism beyond which I can
not follow :)
Seriously, ask Guido about the influence of C vs. fortran. Somewhere
you can find him quoted as saying that python was originally intended
to "bridge the gap between the shell and C". I've never heard him talk
about fortran.
But this academic discussion is honestly a little pointless. The OP
was referring to a expectation, coming from C, that is not fulfilled
in python. What's wrong with mentioning it somewhere for the sake of
helping C programmers?
By the way, assignments in conditionals. Guido explicitly referred to
C when he forbade assignment in conditionals, citing common
typos/errors in C code such as if( x = 5 ){ .... } instead of if( x ==
5 ){ ..... }. So even he realized that warning people about different
usage in python and C is a good thing. Expectations from C work
sometimes, and sometimes they don't. In latter case a little warning
is useful.
Cheers,
Daniel
>> So I'd think that putting a warning in a FAQ or a Python Gotchas list
>> about ++n would be very useful for many users.
>
> Might eventually be useful, but I can't hardly recall of more than a
> couple threads on this topic in 8+ years.
--
I doubt that there are many. Plus, you misspelled them from the more obvious
n++
and
n--
which *do* fail with a SyntaxError. I think I faintly remember trying those
in my early Python days and immediately went for "+=" when I saw them fail
(as I had expected).
Stefan
On Mon, 6 Jul 2009 19:48:39 -0700, Daniel Fetchinson
<fetch...@googlemail.com> declaimed the following in
gmane.comp.python.general:
> Yes, there are plenty of languages other than Java and C, but the
> influence of C is admittedly huge in Python. Why do you think loops
> are called "for", conditionals "if" or "while", functions return via
> "return", loops terminate via "break" and keep going via "continue"
> and why is comparison written as "==", etc, etc? All of these are
> coming from C (or an even earlier language) and my point is that users
for, if, and return were common keywords in FORTRAN.
Not to mention BASIC
Both of which predate C
--
__________________________________________________________________________
Guido was probably influenced by the ALGOL language stream, which used "for" and "if". ALGOL 60 was a joint American and European effort and was significant in the late 50s and 60's.
Guido's fellow countryman, Edsgar Dijkstra, took this publication language (the ALGOL60 version) and produced a compiler for it. (It was not the first, but was very early on). Then B. Randell and L.J. Russell visited him, learnt from his experiences and returned to the UK to produce the KDF9 Whetstone ALGOL60 Compiler. Their book "ALGOL 60 Implementation" was a very early and influential book in the field and occupies a significant place in the history of computing. Computer language designers, including Nicholas Wirth (Pascal, Modula, Oberon), have been influenced by ALGOL.
Sadly, "C" and its ilk, come from a totally different stream of language development beginning with the likes of "CPL", "BCPL", "B" and developing into "C" and "C++". This stream was originally focussed on language portability and performance. This stream was much closer to the assembler language end of the language spectrum, whereas the other stream was heavily biased towards publication and later teaching.
I could say more but will restrain myself.
My 2c
Phil
FWIW "++" reeks of assembler language notation.
The KDF9 Whetstone ALGOL60 Compiler was the one I used at Whetstone for 1-Dimensional Transient Heat-Flow calculations and Steam-Table generation. Our course on it was 2.5 days long. We had wonderful training by English Electric, Kidsgrove staff. I hate to think how long the same course would be now, a month?
Okay, so where does one stop? I'd say C deserves special treatment as
opposed to all the other languages you mentioned because Guido himself
admits to influences from C (and ABC but I hope you won't assume that
ABC is a widely used language).
Maybe you didn't read these messages from me in this thread:
By the way, assignments in conditionals. Guido explicitly referred to
C when he forbade assignment in conditionals, citing common
typos/errors in C code such as if( x = 5 ){ .... } instead of if( x ==
5 ){ ..... }. So even he realized that warning people about different
usage in python and C is a good thing. Expectations from C work
sometimes, and sometimes they don't. In latter case a little warning
is useful.
And also,
Seriously, ask Guido about the influence of C vs. fortran (or cobol,
ada, pascal, etc). Somewhere you can find him quoted as saying that
python was originally intended to "bridge the gap between the shell
and C". I've never heard him talk about fortran (or cobol, ada,
pascal, etc).
So don't get me wrong, I'm sufficiently impressed by your knowledge of
various computer languages, I admit to only knowing C and basic and
some fortran (and of course python :)), but if Guido himself thinks
the influence of C on python is more important than the others, then
let's not doubt him.
And yes, I shamelessly admit to arguing based on a higher authority
and not based on merit, but in this case it's appropriate, I think :)
> Lawrence D'Oliveiro wrote:
>>
>> I wonder how many people have been tripped up by the fact that
>>
>> ++n
>>
>> and
>>
>> --n
>>
>> fail silently for numeric-valued n.
>
> I doubt that there are many. Plus, you misspelled them from the more
> obvious
>
> n++
>
> and
>
> n--
>
> which *do* fail with a SyntaxError.
Funny, you accuse me of "misspelling", when it's _your_ version that fails
with errors!
> I wonder whether the problem with assignment in conditionals in C is due
> to the assignment operator being "=". If it was ":=", would the error
> still occur?
One of the original C designers, Kernighan or Ritchie, admitted that he made
the assignment operator "=" instead of ":=" just to save typing one
character, because he thought assignments were more common than tests for
equality.
Here's another toy example:
class Toy(int):
def __init__(self, value):
self._incrd = False
int.__init__(self, value)
def incrHalf(self):
self._incrd = True
def __pos__(self):
if self._incrd:
return self.__class__(self+1)
else:
p = self.__class__(self)
p.incrHalf()
return p
def __add__(self, other):
return self.__class__(int(self)+other)
nows122[126]~% python -i toy.py
>>> i=Toy(5)
>>> +i
5
>>> ++i
6
>>> +++i
6
>>> +i++i
10
>>> +(+i++i)
10
>>> (++i)++i
11
In algol 68 there was one thing strictly forbidden: putting two
operators behind each other:
x := y** -b .comment must be x := y**(-b) .comment
This is quite a sensible rule, especially when, like in Python,
two special characters can be run together to denote a different
operator.
Examples abound : +:= **
A consequence is that 'a*-b'
would be illegal. It would become 'a*(-b)'
Worse is that x=-q would be illegal.
Because unlike in algol 68 in python whitespace is relevant,
we could get by with requiring whitespace:
x= -q # okay
a<b and -a<c and -b < -d # okay
8 ** -2 # okay
Once a c-addict is forced to write
+ +a
she will realize that probably the operator is + is applied to
+a, and that a ++ has no meaning.
>--
>Gabriel Genellina
Groetjes Albert
--
--
Albert van der Horst, UTRECHT,THE NETHERLANDS
Economic growth -- being exponential -- ultimately falters.
albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst
This is actually quite thoroughly untrue. In python, *indentation* is
significant. Whitespace (internal to a line) is not. You can even call
methods like this if you want:
>>> s = 'abc'
>>> s . upper()
ABC
Obviously, that's A Bad Idea(tm), but python's parser won't stop you.
The ++ operator gotcha is so minor that I can't remember anyone actually
asking about it on the list (who was actually facing it as a
problem--this thread was started by idle speculation). Can we not
change the language syntax to address non-issues?
Practicality beats purity, a.k.a. don't you have something better to do?
Cheers,
Cliff
You could have an IDE where you specify which language you're more
familiar with and then have it display warnings likely to be relevant
to you. People could collaborate to add support for gradually more
niche languages.
Python could continue to work the way it was designed to and people
documenting python wouldn't have to worry about this kind of issue. :)
2009/7/6 Lawrence D'Oliveiro <l...@geek-central.gen.new_zealand>:
> I wonder how many people have been tripped up by the fact that
>
> ++n
>
> and
>
> --n
>
> fail silently for numeric-valued n.
>
You totally don't get it. You describe how python is now.
I propose a change to be made to python. Small wonder that that is
different from what it is now.
>
>>>> s = 'abc'
>>>> s . upper()
>ABC
You prove nothing by giving examples.
You can disprove by giving one counter example,
here it goes.
Whitespace (internal to a line) is significant.
In Python you cannot change
xleftgoing = 123000000
to
x left going = 123 000 000
(You can in Algol68)
>Obviously, that's A Bad Idea(tm), but python's parser won't stop you.
What is a bad idea?
Apparently you are not talking about my idea of changing the parser.
("Pythons parser won't stop you from changing the parser" doesn't
make sense.)
>The ++ operator gotcha is so minor that I can't remember anyone actually
>asking about it on the list (who was actually facing it as a
>problem--this thread was started by idle speculation). Can we not
>change the language syntax to address non-issues?
As other languages have an Eleventh Commandment against concatenating
operators, the larger issue is hardly futile.
>
>Practicality beats purity, a.k.a. don't you have something better to do?
I'm having a great time, thank you!
>Cheers,
>Cliff
I had a feeling that counterexample would be coming sooner or later.
However, it doesn't really address the change you're looking for.
Internal whitespace *is* irrelevant, except insofar as it can be used to
delimit different tokens in parsing. If tokens are separate, they are
separate, and no more or less whitespace is going to make any
difference.
Again, I'm describing how python is now. Which is not to say it
couldn't be changed, I just want to make sure you understand how deep
into the heart of python you are trying to cut. You make it sound like
a small change, but it is not. You are proposing changing the parsing
rules, which completely changes the scope of what is possible and what
isn't with python syntax. All to solve a problem that, so far, hasn't
been proven to exist in anything other than a speculative way.
You're trying to turn an ocean liner around because you left your
sunscreen on the dock.
Cheers,
Cliff