Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Problem with exponentiation: -2**2 gives 4 instead of -4

15 views
Skip to first unread message

Arjen Markus

unread,
May 22, 2009, 6:56:41 AM5/22/09
to
Hello,

I ran into a problem with exponentiation in Tcl 8.5.0:

expr {-2**2} gives 4 where I would expect -4 as an answer.

If this has been solved in later version, then please ignore this
report. (I will have to
upgrade anyway ;)).

Regards,

Arjen

Richard Owlett

unread,
May 22, 2009, 7:07:42 AM5/22/09
to

????
When is a negative number squared ever negative?
????

Jonathan Bromley

unread,
May 22, 2009, 7:04:45 AM5/22/09
to
On Fri, 22 May 2009 03:56:41 -0700 (PDT), Arjen Markus
<arjen....@wldelft.nl> wrote:

>Hello,
>
>I ran into a problem with exponentiation in Tcl 8.5.0:
>
>expr {-2**2} gives 4 where I would expect -4 as an answer.

Personally, I would expect -2**2 to parse as (-2)**2,
which was positive when I was at school; if I wanted
to get -4 I would probably ask for -(2**2).

Of course, as I get older my grip on maths gets shakier,
so I could be wrong...
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
jonathan...@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.

Arjen Markus

unread,
May 22, 2009, 7:37:27 AM5/22/09
to
On 22 mei, 13:04, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
wrote:

> On Fri, 22 May 2009 03:56:41 -0700 (PDT), Arjen Markus
>
> <arjen.mar...@wldelft.nl> wrote:
> >Hello,
>
> >I ran into a problem with exponentiation in Tcl 8.5.0:
>
> >expr {-2**2} gives 4 where I would expect -4 as an answer.
>
> Personally, I would expect -2**2 to parse as (-2)**2,
> which was positive when I was at school; if I wanted
> to get -4 I would probably ask for -(2**2).
>
> Of course, as I get older my grip on maths gets shakier,
> so I could be wrong...
> --
> Jonathan Bromley, Consultant
>
> DOULOS - Developing Design Know-how
> VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services
>
> Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
> jonathan.brom...@MYCOMPANY.comhttp://www.MYCOMPANY.com

>
> The contents of this message may contain personal views which
> are not the views of Doulos Ltd., unless specifically stated.

I expect -2**2 to parse as: -(2**2) - it is a literal expression, it
is
not:
set x -2
expr {$x**2}

I came across this in an expression like:

exp( -$y**2/$D }


Regards,

Arjen

Arjen Markus

unread,
May 22, 2009, 7:50:43 AM5/22/09
to
> Arjen- Tekst uit oorspronkelijk bericht niet weergeven -
>
> - Tekst uit oorspronkelijk bericht weergeven -

Furthermore, I would expect that "0-expression" and "-expression" give
the same value, but:

expr {0-2**2} gives -4

and

expr {-2**2} gives 4

It may be my Fortran background, but I find the current parsing
somewhat
disconcerting.

Regards,

Arjen

Jonathan Bromley

unread,
May 22, 2009, 8:23:35 AM5/22/09
to
On Fri, 22 May 2009 04:50:43 -0700 (PDT), Arjen Markus wrote:


> I expect -2**2 to parse as: -(2**2)

[...]


>Furthermore, I would expect that "0-expression" and
> "-expression" give the same value, but:
> expr {0-2**2} gives -4
>and
> expr {-2**2} gives 4
>
>It may be my Fortran background, but I find the current parsing
>somewhat disconcerting.

Fascinating. From various languages, I would expect monadic
operators to bind more tightly than any dyadic operator.
Monadic - is not the same as dyadic -; it isn't a shorthand
for "0-" (not in my lexicon, anyway). I'd forgotten the
Fortran behaviour.

I assume Tcl was guided by C, but I don't know C sufficiently
intimately to be sure of its rules. I've learnt too many
different languages in my time, and don't trust my increasingly
flaky memory to hold operator precedence tables; parentheses
are my friends.
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK

jonathan...@MYCOMPANY.com

Kevin Kenny

unread,
May 22, 2009, 8:34:02 AM5/22/09
to
Arjen Markus wrote:

> I expect -2**2 to parse as: -(2**2) - it is a literal expression, it
> is
> not:
> set x -2
> expr {$x**2}
>
> I came across this in an expression like:
>
> exp( -$y**2/$D }

Unary operators bind more tightly than any binary operator.
The [expr] man page gives the binding strengths (strongest to
weakest) as:

Unary - + ~ !
**
* / %
+ -
<< >>
< > <= >=
== !=
eq ne
in ni
&
|
&&
||
Ternary ? :

So the parse tree of your second expression is

exp(-$y**2/$D):

exp ( @ )
|
( @ / @ )
| |
| $D
|
( @ ** @ )
| |
| 2
|
( - @ )
|
$y

You got tripped by coming from Fortran, where unary
operations bind less tightly than exponentiation (and,
puzzlingly, than multiplication and division). Tcl
is not Fortran, and its precedences are slightly
different. Other differences to watch out for:

- Fortran binds .EQ. and .GE. equally to .LT.,
.LE., .GE., .GT. . Tcl treats them equally.
- Fortran binds // more loosely than addition
and subtraction. Tcl considers % as equal
to * and /
- Tcl's & and | bind more tightly than && and ||
- Fortran associates ** from right to left.
Tcl associates it from left to right. (I am
on record as having been opposed to that
decision, but I take it as made.)

Please excuse my dear Aunt Sally.*

--
73 de ke9tv/2, Kevin

* For non-English speakers, and those who have forgotten
high-school algebra, it's an old mnemonic:
'parentheses, exponents, multiplication, division, addition,
subtraction'.)

Arjen Markus

unread,
May 22, 2009, 8:53:40 AM5/22/09
to

Okay, from all the responses, it seems that -$y**2 should indeed
be interpreted as (-$y)**2 and not as -($y**2).

Still, I interpret the following mathematical (!) expression exp(-
y**2) as:

exp(-y**2) = exp(-(y*y)) = 1/exp(y*y)

in that sense a unary minus is binding less closely than
exponentiation (well,
if you write it like:
2
-y
e

that does make sense :).

As for the right/left association of **, I seem to remember that we
corrected that,
the left associativity being the easy way to implement **. Indeed:

expr {2**2**3} -> 256

expr {2**(2**3)} -> 256

expr {(2**2)**3} -> 64

(using Tcl 8.5.0 again)

Regards,

Arjen

Arjen Markus

unread,
May 23, 2009, 5:00:30 AM5/23/09
to
On 22 mei, 14:34, Kevin Kenny <kenn...@acm.org> wrote:

As it happens, I found in a book on AWK that I am reading that that
language puts exponentiation before unary minus too.

I am not sure about the precedences in Fortran you cite - // is a
string operation and can not be mixed with + or -, in Fortran %
is done via the mod (or modulo) function (depending on what you
want done with negative arguments) and the binary operations & and |
are also done with functions.

Whether unary minus is tying less tightly than * or /, I do not
know. How would "x* -y" be interpreted? (One tiny experiment
suggests: x*(-y), but that is hardly proof of anything ;)).

Anyway, this is the way it is, I now know.

Regards,

Arjen

suchenwi

unread,
May 23, 2009, 5:14:28 AM5/23/09
to
Arjen Markus schrieb:

> How would "x* -y" be interpreted? (One tiny experiment
> suggests: x*(-y), but that is hardly proof of anything ;)).

How else could it? * is not optionally an unary postfix operator... :^)

Donald Arseneau

unread,
May 23, 2009, 9:22:33 AM5/23/09
to
On May 22, 5:53 am, Arjen Markus <arjen.mar...@wldelft.nl> wrote:

> Okay, from all the responses, it seems that -$y**2 should indeed
> be interpreted as (-$y)**2 and not as -($y**2).
>
> Still, I interpret the following mathematical (!) expression

> exp(-y**2) as:


>
> exp(-y**2) = exp(-(y*y)) = 1/exp(y*y)
>
> in that sense a unary minus is binding less closely than
> exponentiation

In written algebra -x² = x² implies x = 0. It is a mistake
for Tcl to bind the unary minus more tightly than exponentiation.

Donald Arseneau

tom.rmadilo

unread,
May 23, 2009, 11:11:35 AM5/23/09
to
On May 23, 6:22 am, Donald Arseneau <a...@triumf.ca> wrote:
> In written algebra -x² = x² implies x = 0.  It is a mistake
> for Tcl to bind the unary minus more tightly than exponentiation.

In written algebra -x² = x² is an equation, not a programming
assignment statement. It is perfectly fine for x to equal zero, since
the point is to solve for x in -x² = x².

Anyway, there is no "logic" involved in the associativity rules in a
programming language. I don't even think that ** has a valid meaning
in C. But every language should provide a method to indicate the
desired parse/calculation order. If not, that would be a very serious
bug, as some expressions could not be represented by the language.
Tcl, like many languages, uses ( and ) to group sub-expressions and
enforce the desired calculation order.


Arjen Markus

unread,
May 23, 2009, 11:23:08 AM5/23/09
to
On 23 mei, 11:14, suchenwi <richard.suchenwirth-

True, I actually find such expressions a bit hard to read ... I later
tried
to examine it more closely using derived types and user-defined
versions of
the operations, so that I could write a message when the operation was
run.

From that experiment I conclude: Kevin is quite right:
unary minus comes later than multiplication, at least in -x*y.

In x*-y the unary minus comes first, but the compiler I used warned
that
support for the sequence *- is an extension ...

I tried to find situations where it matters whether unary minus comes
before
multiplication or after, mathematically I do not think that there is
a
difference (at least with ordinary numbers).

My, these are subtle issues! (In C these are more complicated than in
Fortran,
as Fortran distinguishes logicals and integers, so that x > y == z is
not
possible, at least not without jumping a hoop or two)

Regards,

Arjen

tom.rmadilo

unread,
May 23, 2009, 11:24:40 AM5/23/09
to
On May 23, 8:11 am, "tom.rmadilo" <tom.rmad...@gmail.com> wrote:
> On May 23, 6:22 am, Donald Arseneau <a...@triumf.ca> wrote:
>
> > In written algebra -x² = x² implies x = 0.  It is a mistake
> > for Tcl to bind the unary minus more tightly than exponentiation.
>
> Anyway, there is no "logic" involved in the associativity rules in a
> programming language. I don't even think that ** has a valid meaning
> in C. But every language should provide a method to indicate the
> desired parse/calculation order.

Probably the best argument for unary - binding more tightly that ** is
that the sign of a number is part of the number, it isn't an operator.
-2 is a negative number. In the expression 0-2, two is a positive
integer. If the result was calculated, you would probably choose to
write the expression as (0-x)**2 and not 0-x**2.

Arjen Markus

unread,
May 24, 2009, 3:12:08 AM5/24/09
to
On 23 mei, 17:24, "tom.rmadilo" <tom.rmad...@gmail.com> wrote:
> On May 23, 8:11 am, "tom.rmadilo" <tom.rmad...@gmail.com> wrote:
>
> > On May 23, 6:22 am, Donald Arseneau <a...@triumf.ca> wrote:
>
> > > In written algebra -x² = x² implies x = 0.  It is a mistake
> > > for Tcl to bind the unary minus more tightly than exponentiation.
>
> > Anyway, there is no "logic" involved in the associativity rules in a
> >programminglanguage. I don't even think that ** has a valid meaning

> > in C. But every language should provide a method to indicate the
> > desired parse/calculation order.
>
> Probably the best argument for unary -bindingmore tightly that ** is
> that thesignof a number is part of the number,itisn't an operator.

> -2 is a negative number. In the expression 0-2, two is a positive
> integer. If the result was calculated, you would probably choose to
> write the expression as (0-x)**2 and not 0-x**2.

No, I do not agree: -$x**2 is computed as (-$x)**2 now, regardless of
the
sign of the number that the variable x holds. If x would have the
value -2,
then this would expand to --2**2. expr "-$x**2" still gives 4.

The whole issue arises only because exponentiation has a higher
precedence
than multiplication. A unary minus can also be seen as an implicit
multiplication
by -1, in which case -$x**2 would become: -1*$x**2.

These precedences are ever so subtle :(.

Regards,

Arjen


Donald Arseneau

unread,
May 24, 2009, 5:31:06 AM5/24/09
to
On May 23, 8:11 am, "tom.rmadilo" <tom.rmad...@gmail.com> wrote:
> On May 23, 6:22 am, Donald Arseneau <a...@triumf.ca> wrote:
>
> > In written algebra -x² = x² implies x = 0. It is a mistake
> > for Tcl to bind the unary minus more tightly than exponentiation.
>
> In written algebra -x² = x² is an equation, not a programming
> assignment statement. It is perfectly fine for x to equal zero, since
> the point is to solve for x in -x² = x².

You are missing the point entirely!

In written algebra (what passes for "real life" here) the negation
applies to the whole x² not the the x alone. Tcl should emulate
the long-standing traditions of algebra for expr syntax.

Tcl's rules have made -x² = x² (-$x**2 == $x**2) an identity
for all x, whereas in algebra that equality only holds for x = 0.

> Anyway, there is no "logic" involved

Not logic, but tradition and expectation. You wouldn't swap the
meaning of + and - on a whim, would you?

> Probably the best argument for unary - binding more tightly that ** is
> that the sign of a number is part of the number, it isn't an operator.


> -2 is a negative number.

But unary - *IS* an operator outside of tcl, as demonstrated by the -

example: x is squared, whether it is positive or negative, then the
result
is negated.


Now this brings us to a really messy bit, and I don't know if this
was
the deciding factor in the decision. eias.

set x 2
expr { $x**2 }
expr $x**2


set x -2
expr { $x**2 }

expr $x**2

Donald Arseneau

Cameron Laird

unread,
May 24, 2009, 8:39:28 AM5/24/09
to
In article <7260d1dc-6741-4930...@p6g2000pre.googlegroups.com>,
Donald Arseneau <as...@triumf.ca> wrote:
.
.

.
>Now this brings us to a really messy bit, and I don't know if this
>was
>the deciding factor in the decision. eias.
>
>set x 2
>expr { $x**2 }
>expr $x**2
>set x -2
>expr { $x**2 }
>expr $x**2
>
>Donald Arseneau

What's the messy bit? As a mathematician, EIAS seems
like a good deal to me; I *want*

-2 ** 2

to evaluate to

+4.

Don Porter

unread,
May 24, 2009, 11:28:42 AM5/24/09
to
Arjen Markus wrote:
> I ran into a problem with exponentiation in Tcl 8.5.0:
>
> expr {-2**2} gives 4 where I would expect -4 as an answer.

See TIPs 123 and 274 and Tcl Patch 655176 (re-exposed for
sake of this reference).

From TIP 123: "The precedence of the exponentiation operator
is thus higher than the multiplication, division and
remainder operations and lower than the unary operations,
in accordance with common definitions."

You might ask Arjen Markus what rationale he had for proposing
that precedence rule. :)

DGP

Donald Arseneau

unread,
May 25, 2009, 4:14:05 AM5/25/09
to
On May 24, 5:39 am, cla...@lairds.us (Cameron Laird) wrote:
> In article <7260d1dc-6741-4930-b0c8-91405a832...@p6g2000pre.googlegroups.com>,

> Donald Arseneau  <a...@triumf.ca> wrote:
>
> >Now this brings us to a really messy bit, and I don't know if this
> >was the deciding factor in the decision.  eias.
>
> >set x 2
> >expr { $x**2 }
> >expr $x**2
> >set x -2
> >expr { $x**2 }
> >expr $x**2

> What's the messy bit?  As a mathematician, EIAS seems


> like a good deal to me; I *want*
>
>     -2 ** 2
>
> to evaluate to
>
>     +4.

WHAT!? I am aghast! As a mathematician, do you want -2² to
equal 4? You must be disappointed, because -2² = -4. If you
mean (-2)² then you must write it that way, with parentheses,
and then you get 4. I don't see how there can be any confusion
or disagreement on this issue, because algebraic notation is
thoroughly standardized on this interpretation.

For creating the ** operator in Tcl expr, indeed any expr syntax,
it would be best to maintain as close an analogy with written
algebraic expressions as possible. The current ** operator
does violate that.

But I see that eias and history have forced the current choice.
Eias says that expr syntax should work the same if the variables
are substituted textually before the expr is evaluated, which
means $x**2 must give the same result as -2**2, when $x == 2.
That forces negation to be more tightly bound to a number than
anything else.

The history is that unary negation was of higher precedence than
multiplication, and that old order can't be changed. I think this
just gets back to the eias issue again, as the original motivation
for that operator precedence.

Although the current choice may be forced, it is still an ugly
wart.

Donald Arseneau

Arjen Markus

unread,
May 25, 2009, 4:39:52 AM5/25/09
to

I have looking at the context of that sentence: he never considered
the issue of -$x**2 :}.

According to the examples given, it all had to do with expressions
like:

$x ** -1

This is a rather awkward oversight, in both our ever so humble
opinions.

Regards,

Arjen and Arjen

Alexandre Ferrieux

unread,
May 25, 2009, 6:05:25 AM5/25/09
to

I would not be so harsh. Your only oversight IMO is just not to have
untangled the knot generated by having unary minus separate (in
priorities) from substraction. Indeed I believe we should have given
higher strength to the intuitive expectation that 0-X == -X.

As it turns out, putting the whole group of unary ops on top is a very
strange decision.
It often goes unnoticed because the only really interesting one for
computations (unary minus) happens to commute with * and / which come
immediately afterwards in priority. So the fact that -3*4 parses as
(-3)*4 is hidden. However, it does not commute with the modulo
operator, in the same prio class as * and /, so we can generate
another example of this awkward ordering without using exponentiation:

expr {-3%4} --> 1
expr {0-3%4} --> -3

So you can see that certainly you have absolutely no reproach to
fear !!!
Of course it is way too late to change that. I don't want a 2nd
Chernobyl or Challenger disaster coming from Tcl aesthetics :-P

-Alex

Alexandre Ferrieux

unread,
May 25, 2009, 6:13:36 AM5/25/09
to
On May 25, 12:05 pm, Alexandre Ferrieux <alexandre.ferri...@gmail.com>
wrote:

>
> It often goes unnoticed because the only really interesting one for
> computations (unary minus) happens to commute with * and / which come
> immediately afterwards in priority.

Uh, for floating-point yes, but of course, as the modulo case
suggests, unary minus does not even commute with integer division:

expr {-3/4} --> -1
expr {0-3/4} --> 0

Again we have really trivial examples that already violate intuition.
Sad and irreversible.

-Alex


Kevin Kenny

unread,
May 25, 2009, 8:36:17 AM5/25/09
to
Alexandre Ferrieux wrote:
> Uh, for floating-point yes, but of course, as the modulo case
> suggests, unary minus does not even commute with integer division:
>
> expr {-3/4} --> -1
> expr {0-3/4} --> 0

For what it's worth, C gets that one wrong as well, making me
wonder whether that's a subtle reason that C never added **.
The modular and integer arithmetic issues are considerably
more subtle, since the operations in question are far more
often used with unsigned (or at least nonnegative) quantities.

This issue is another one to put on the list with 'death to octal'
and 'creative writing': The list in question is "those changes
that will probably fix more bugs than they introduce, because
existing behaviour is surprising." That's one level down from
"I don't have any code that depends on the surprising behaviour,
but someone *else* might, so let's not fix it."

The thing that this is really awkward for is polynomials with
a leading factor of -1.
-x**4 + 4. * x**3 - 6. * x**2 + 4. * x - 1
Yes, I know this is a bad example, anyone sane would write
-(x-1)**4
OOPS! I mean
-((x-1)**4)
This is very bad, it's right up there with making exponentiation
left-associative. (And I checked the code: we correctly make
it right-associative. But the manual lies. Can we please fix
the documentation and not the code for that one?)

Don Porter

unread,
May 25, 2009, 12:47:00 PM5/25/09
to
Donald Arseneau wrote:
> But I see that eias and history have forced the current choice.

EIAS has nothing at all to do with it.

The ** operator has the precedence it does because that's
what the TIP introducing it proposed.

DGP

tom.rmadilo

unread,
May 25, 2009, 12:55:09 PM5/25/09
to
On May 25, 1:14 am, Donald Arseneau <a...@triumf.ca> wrote:
> On May 24, 5:39 am, cla...@lairds.us (Cameron Laird) wrote:
 As a mathematician, EIAS seems
> > like a good deal to me; I *want*
>
> >     -2 ** 2
>
> > to evaluate to
>
> >     +4.
>
> WHAT!?  I am aghast!  As a mathematician, do you want  -2²  to
> equal 4?  You must be disappointed, because -2²  = -4.  If you
> mean (-2)² then you must write it that way, with parentheses,
> and then you get 4.  I don't see how there can be any confusion
> or disagreement on this issue, because algebraic notation is
> thoroughly standardized on this interpretation.

You seem to think that mathematicians don't think of -2 as a distinct
number which could be multiplied by itself.

If squaring -2 requires (-2)**2, then so should 2: (2)**2. But
mathematics is not programming language. In a Tcl expression all
variables have known values. In a mathematical equation, the x's and
y's are unknowns. In mathematics, -x^2 is not an equation, it is
meaningless, but -2 is a negative number.

In a mathematical equation like y = x^2 - 2x + 1, the implied meaning
is that each power of x is preceded by a coefficient. The coefficient
has an associated sign. The above can be factored to y = (x - 1)(x -
1) = (x - 1)^2. Somehow mathematicians know how to square (x - 1)
correctly.

What result should Tcl return for this example: -2**0.5?

Don Porter

unread,
May 25, 2009, 12:57:15 PM5/25/09
to
Don Porter wrote:
> See TIPs 123 and 274 and Tcl Patch 655176 (re-exposed for
> sake of this reference).

As well as Tcl Bug 1667660.

DGP

Alexandre Ferrieux

unread,
May 25, 2009, 1:33:43 PM5/25/09
to
On May 25, 2:36 pm, Kevin Kenny <kenn...@acm.org> wrote:
> This is very bad, it's right up there with making exponentiation
> left-associative. (And I checked the code: we correctly make
> it right-associative. But the manual lies. Can we please fix
> the documentation and not the code for that one?)

Would a rephrasing from

"All of the binary operators group left-to-right within the same
precedence level"

to

"All of the binary operators but exponentiation group left-to-right
within the same precedence level ; exponentiation groups right-to-left
[add as final example 2**3**2==512]"

please you ?

-Alex

Don Porter

unread,
May 25, 2009, 1:43:38 PM5/25/09
to

Sorry. Wrong thread.

DGP

Kevin Kenny

unread,
May 25, 2009, 6:35:41 PM5/25/09
to
Alexandre Ferrieux wrote:
> Would a rephrasing from
>
> "All of the binary operators group left-to-right within the same
> precedence level"
>
> to
>
> "All of the binary operators but exponentiation group left-to-right
> within the same precedence level ; exponentiation groups right-to-left
> [add as final example 2**3**2==512]"
>
> please you ?

Looks good. Thanks!

Donald Arseneau

unread,
May 26, 2009, 12:07:11 AM5/26/09
to
On May 25, 9:55 am, "tom.rmadilo" <tom.rmad...@gmail.com> wrote:
> On May 25, 1:14 am, Donald Arseneau <a...@triumf.ca> wrote:> On May 24, 5:39 am, cla...@lairds.us (Cameron Laird) wrote:
>
> As a mathematician, EIAS seems
>
> > > like a good deal to me; I *want*
>
> > > -2 ** 2
>
> > > to evaluate to
>
> > > +4.
>
> > WHAT!? I am aghast! As a mathematician, do you want -2² to
> > equal 4? You must be disappointed, because -2² = -4. If you
> > mean (-2)² then you must write it that way, with parentheses,
> > and then you get 4. I don't see how there can be any confusion
> > or disagreement on this issue, because algebraic notation is
> > thoroughly standardized on this interpretation.
>
> You seem to think that mathematicians don't think of -2 as a distinct
> number which could be multiplied by itself.

Don't be ridiculous!

At issue is the format used for inputting Tcl expressions
and relating that to the notation for writing algebraic
expressions.

The written text -2² *means* that 2 is squared and the result
negated. It does not mean the square of -2. If you have some
evidence that this notation is not universal, I would love to
see it.

If I was frustrated yesterday with banging my head against a wall,
it is even worse now. How can this be unclear to other people?

> In a mathematical equation like y = x^2 - 2x + 1, the implied meaning
> is that each power of x is preceded by a coefficient.

Here you are making things up. There are no implied coefficients
there, and I don't see how this is relevant. (I can only speculate
vaguely that this made-up rule fixes some problems you have
interpreting expressions caused by your mis-remembering the
order of precedence for negation.)

> What result should Tcl return for this example: -2**0.5?

As I said, in the post you are replying to, the issue of *should*
is constrained by consistency under eias and by history. To keep
best consistency with real-world algebraic notation, disregarding
the specific Tcl constraints, -2**0.5 should give -1.414...
To keep consistency between expr {-$x**2} and expr "-$x**2"
it is constraind to give the algebraicly incorrect 1.414...

Donald Arseneau

Donald Arseneau

unread,
May 26, 2009, 12:34:29 AM5/26/09
to

Piffle. So I should assume the TIP and eventually the
Tcl language is entirely arbitrary, with no consideration
of relevant issues or of the practice and experience
elsewhere?

I still hope that at least anomalous high operator
precedence for unary minus, going back to the origins
of tcl, came out of a need rather than capriciousness.

Donald Arseneau as...@triumf.ca

Alexandre Ferrieux

unread,
May 26, 2009, 5:15:31 AM5/26/09
to

Fix committed to HEAD.

Now regarding your suggestion to be more courageous and improve the
language, what about a TIP named "Lower the priority of Unary Minus" ?
Indeed, of the four ops that are today making up the top priority
class:

- unary minus is the real killer
- unary plus is a no-op (but the TIP could recommend to demote
it too for symmetry)
- unary binary ops ~ and ! have nothing to do with the ususal
math notation, so they are okay as long as they are higher than | & et
al.

Do you agree ?

-Alex

Kevin Kenny

unread,
May 26, 2009, 6:51:13 AM5/26/09
to
Donald Arseneau wrote:
> I still hope that at least anomalous high operator
> precedence for unary minus, going back to the origins
> of tcl, came out of a need rather than capriciousness.

It came about because Tcl copied C. And in C it doesn't
matter, because C doesn't have '**'. Tcl didn't have '**'
at first, either, and there was no good place to fit it
into the existing precedences. And rearranging the
precedences runs the risk of breaking code silently.

If we could have told Ousterhout in 1990 that we'd be
adding ** in 2007 and he needed to realign precedences
to accommodate it, I'm sure he'd have been happy to
oblige.

Kevin Kenny

unread,
May 26, 2009, 7:01:59 AM5/26/09
to
Donald Arseneau wrote:>
> As I said, in the post you are replying to, the issue of *should*
> is constrained by consistency under eias and by history. To keep
> best consistency with real-world algebraic notation, disregarding
> the specific Tcl constraints, -2**0.5 should give -1.414...
> To keep consistency between expr {-$x**2} and expr "-$x**2"
> it is constraind to give the algebraicly incorrect 1.414...

It's not even an EIAS issue. If we were designing [expr]
from scratch or willing to accept the incompatibility,
it could simply not include a leading sign in *its* notion
of a numeric literal. Variable substitution outside
[expr] is another kettle of fish entirely. I'd be
no more bothered by:

set x -2
expr "$x**2" -> -4
expr {$x**2} -> 4

than I am by

set x 1+1
expr "$x**2" -> 2
expr {$x**2} -> error

And I think that

set x {[rm -rf ~/*]}
expr {$x**2} -> error without side effects

is a very good idea. While in that case [expr "$x**2"]
falls under the general category of "kids, don't try
this at home."

But we're hobbled here by backward compatibility.
It's the prospect of breaking existing code silently
that is troubling.

Kevin Kenny

unread,
May 26, 2009, 7:31:36 AM5/26/09
to
Alexandre Ferrieux wrote:
> Now regarding your suggestion to be more courageous and improve the
> language, what about a TIP named "Lower the priority of Unary Minus" ?
> Indeed, of the four ops that are today making up the top priority
> class:
>
> - unary minus is the real killer
> - unary plus is a no-op (but the TIP could recommend to demote
> it too for symmetry)
> - unary binary ops ~ and ! have nothing to do with the ususal
> math notation, so they are okay as long as they are higher than | & et
> al.
>
> Do you agree ?

(1) The TIP won't pass, because we *are* afraid. I think about
the only way to get it in would be to go through *two*
complete release cycles. In the first, forbid expressions
whose interpretation changes with the change, and in the
second, allow the correct precedence.

And the problem with that -- octal and creative writing also
are amenable to similar approaches with the same problem --
is that there is an entire release where the only user-visible
change is the introduction of apparently gratuitous errors
in previously working code.

The fact that this appeared to have been the only politically
viable approach for octal was why I gave up on it, although
I still complain from time to time.

(2) With that out of the way, I don't think your proposed
change is quite right just yet. We now define ~$x as being
equivalent to -1-$x, and so it belongs up with unary + and -.
I need to think more about !.

Alexandre Ferrieux

unread,
May 26, 2009, 8:02:44 AM5/26/09
to
On May 26, 12:51 pm, Kevin Kenny <kenn...@acm.org> wrote:
>
> If we could have told Ousterhout in 1990 that we'd be
> adding ** in 2007 and he needed to realign precedences
> to accommodate it, I'm sure he'd have been happy to
> oblige.

Hmmm, right, but as mentioned in the other thread, / and % have been
there all the time, and expose the anomalous priority of unary minus
all the same:

expr {0-3/4} --> 0
expr {-3/4} --> -1

So it might not be "capriciousness", but just a bit of
overgeneralization, as if being unary was a strong mark of likeness
for [+-!~].
The correct analysis (that unary and binary minus should have the same
prio) is clear in hindsight, but the side-effects have been mild
enough that no one of us noticed this day-one quirk.

-Alex

Don Porter

unread,
May 26, 2009, 8:09:03 AM5/26/09
to
Donald Arseneau wrote:
>> The ** operator has the precedence it does because that's
>> what the TIP introducing it proposed.

> Piffle. So I should assume the TIP and eventually the
> Tcl language is entirely arbitrary, with no consideration
> of relevant issues or of the practice and experience
> elsewhere?

No. I'm saying the attempts here to find deep meaning
and intent in this precedence choice are a pointless
sideshow. The reasons are recorded. There aren't some
other semi-secret ones to be discovered.

> I still hope that at least anomalous high operator
> precedence for unary minus, going back to the origins
> of tcl, came out of a need rather than capriciousness.

At least I assume that someone willing to go to the trouble
of writing a TIP and constructing an initial implementation
has a need, and has constructed something that satisfies the
need.

If we botched the review, then we botched the review, and
we'll need to consider what "next step" if any makes sense.

No caprice here that I can see. Perhaps too much trust
that someone has asked for what they really need. Perhaps
too much assumption among the reviewers that "someone else"
is checking every last detail. And definitely too little
community engagement if a flaw of alleged great importance
can go unnoticed for nearly six years.

DGP

Don Porter

unread,
May 26, 2009, 8:11:46 AM5/26/09
to
Kevin Kenny wrote:
> It's not even an EIAS issue. If we were designing [expr]
> from scratch or willing to accept the incompatibility,
> it could simply not include a leading sign in *its* notion
> of a numeric literal.

That is the way the [expr] parser works. All literal
"-" and "+" characters in the expression are operators.
None are treated as part of a literal number.

DGP

Don Porter

unread,
May 26, 2009, 8:20:42 AM5/26/09
to
Alexandre Ferrieux wrote:
> So it might not be "capriciousness", but just a bit of
> overgeneralization, as if being unary was a strong mark of likeness
> for [+-!~].

Attempting to divine intent is error prone, but I observe
that until Tcl 8.5, the [expr] parser was recursive and
every additional precedence level implied another level
of recursion, with attendant costs in run time and stack
consumption. I would guess that would create pressure
to reduce the number of distinct precedence levels in
the system. And with no ** operator to expose the worst
examples, collapsing operators into one precedence is
one bit of "premature optimization" I could see happening.

DGP

Alexandre Ferrieux

unread,
May 26, 2009, 11:03:27 AM5/26/09
to
On May 26, 2:20 pm, Don Porter <dgpor...@verizon.net> wrote:
>
> [...] I would guess that would create pressure

> to reduce the number of distinct precedence levels in
> the system.  And with no ** operator to expose the worst
> examples, collapsing operators into one precedence is
> one bit of "premature optimization" I could see happening.

Well, in this particular case the two options have the same number of
levels, so I'm afraid the theory doesn't hold :-}

-Alex

tom.rmadilo

unread,
May 26, 2009, 1:46:05 PM5/26/09
to

That is good to know, and it helps the analysis.

The EIAS explanation make it sound like Tcl is somehow unique among
programming languages, in that the developers got something wrong.
There has to be a defined order of precedence: how will a program
order instructions for execution? [expr] isn't unique, it is just a
special case with for semi-numeric calculations.

I don't really think it is valid to apply algebraic notation to
programming statements, but I am still struck that there is some
confusion about the difference between the negation operator (unary
minus) and the subtraction operator (binary minus). Even in algebra,
the two are kept separate.

For instance, in defining different types of number domains, you run
into stuff like this: if a > b, then a - b is non-negative. Note that
"a" and "b" is a notation which includes the sign. Both a and b could
be negative in the above condition. In Tcl, like many programming
languages, a and b could be substituted in many different ways.

In the example:

expr {0 - 3/4} => 0, 3/4 is a number (0), so it is equivalent to [expr
{0 - 0}]. If we take the first 0 to be a, then we could chose a number
b less than 0 and see what binary minus gets us:

expr {0 - -3/4} => 1, so the general rule of numbers holds here.

Otherwise, instead of complaining about the evils of unary minus, we
should complain about 3/4 == 0. Which is more or less "intuitive"
here?

Unary minus, is an operator which is applied first, when all these
unary operators are applied, then binary minus can be applied:

expr {1---2**2} => -3
expr {1-+-2**2} => -3
expr {1+-2**2} => 5
expr {1--2.0**-2.0} => .75 (1-1.0/-2**2)

Joe English

unread,
May 26, 2009, 1:49:58 PM5/26/09
to

Donald Arseneau wrote:

> At issue is the format used for inputting Tcl expressions
> and relating that to the notation for writing algebraic
> expressions.

Yep. And the two notations are not identical.
Tcl expr syntax is an approximation meant to be
evocative of algebraic notation -- not isomorphic to,
merely evocative of -- and that's all.

The canonical example is (using TeX notation,
since it can't be reproduced in ASCII):

\begin{displaymath}
y = ax^2 + bx + c
\end{displaymath}

which is expressed in Tcl as:

set y [expr {$a * $x**2 + $b * $x + $c}]

There are multiple significant differences between the two notations.
To name a few: $ to indicate variable references; infix operator asterisk
instead of juxtaposition to indicate multiplication; infix operator
double-asterisk instead of typographical superscripts to indicate
exponentiation; multiple-character variable names (not shown);
single font variable names restricted to the roman alphabet;
plus the words "set" and "expr" and the additional braces and brackets
for punctuation.

Somehow, most Tcl programmers manage to deal with these differences.


[ Not to mention that the two have utterly different meanings:
the first expresses an equation, the second a computation.
But that's not really relevant. ]


> The written text -2� *means* that 2 is squared and the result
> negated. It does not mean the square of -2. If you have some
> evidence that this notation is not universal, I would love to
> see it.

[ Superscripts in mathematics are used for *many* things besides
exponentiation. But that's not really relevant. ]

If you think of "**" as a poor approximation to typographical
superscripts necessitated by the limitations of the ASCII medium,
then yeah, the relative precedence of "-" and "**" could be
considered wrong.

But if you think of "**" as an infix operator like "+", "-", "*",
"/", "&&", "||", and "^" -- which is, in fact, exactly how Tcl
interprets it -- then the relative precedences make perfect sense.

--Joe English

tom.rmadilo

unread,
May 26, 2009, 3:17:53 PM5/26/09
to
On May 26, 10:49 am, Joe English <jengl...@fdip.bad-monkeys.net>
wrote:

> Somehow, most Tcl programmers manage to deal with these differences.

I agree, we are quite advanced here.

The idea that Tcl developers are just making stuff up for no good
reason is one which could only be based upon a lack of familiarity
with the history of Tcl development. The first point is that Tcl was
designed to leverage existing C libraries and executable programs of
all flavors. But C is the starting point in Tcl development.

Every introductory programming language book I have seen starts off
with some discussion of the order of execution, including precedence
rules. The authors usually take great pains to point out the expected
behavior, especially when the rules can bite you.

Take the first Dr. O book. Chapter 2 contains the first code example:

expr 2 + 2

On the next page, Ousterhout explains "The expr command supports an
expression syntax similar to that of expressions in ANSI C, including
the same order of precedence rules and most of the C operators."

Or look at _The C Programming Language_, page 10, the second example,
the first after the famous "hello, world" example is about conversion
of degrees F to C. One statement is explained the conversion
expression:

celsius = 5 * (fahr -32) / 9; Explained:

"The reason for multiplying by 5 and then dividing by 9 instead of
just multiplying by 5/9 is that in C, as in many other languages,
integer division truncates: any fractional part is discarded. Since 5
and 9 are integers, 5/9 would be truncated to zero..."

MSE...@gmail.com

unread,
May 27, 2009, 3:43:32 AM5/27/09
to

And on page 49 of the same book (mine is dated 1978) the unary minus
has clear precedence over *, / and %.

Donald Arseneau

unread,
May 27, 2009, 5:44:36 AM5/27/09
to
On May 26, 10:49 am, Joe English <jengl...@fdip.bad-monkeys.net>
wrote:
> Yep.  And the two notations are not identical.
> Tcl expr syntax is an approximation meant to be
> evocative of algebraic notation -- not isomorphic to,
> merely evocative of -- and that's all.

Point taken. There are a lot of more serious differences than the
unary minus, like floats vs real numbers, int vs integer, ascii
character set limitations, [ ], etc. The similarity of variable
substitution ($x vs (italic)x) is also evocative but not isomorphic,
especially when string substitution occurs.

I do still think the current behavior is the right fit for the
circumstances, including having string variable substitution
give the same result as numeric variable substitution. But
as Kevin says, this is a very minor point compared to other
discrepancies between string substitution (by the parser)
and numeric substitution (by expr).

Donald Arseneau

tom.rmadilo

unread,
May 27, 2009, 11:12:55 AM5/27/09
to

Here is a very helpful description of unary minus:

http://teaching.idallen.com/cst8152/97s/unary_minus.html

Excerpts:

The minus sign ('-') is use for two different operations in
mathematics. Not only does it perform subtraction of two operands, it
also negates a single operand:

1. a - b: subtract variable b from variable a
2. -x: change the sign of the value of variable x (unary minus)

The same is true in most programming languages. The minus operator is
said to be overloaded.

.... and

Unary minus has high precedence; it is done before most other
arithmetic operations....

The above grammar correctly parses expressions with both subtraction
and unary minus, such as:

* a - b - c
* -a - -b - -c
* - - - a - - - - b - - - - - c

tom.rmadilo

unread,
May 27, 2009, 1:37:31 PM5/27/09
to
I did find an apparent bug in the new operator **.

Of course, this might just be how things are done in programming
languages, so it might not be a bug.

In math:

a**0 == 1, a != 0, and
0**a == 0, a != 0.
0**0 is an indeterminant

In Tcl (8.5.7):

expr {0**0} => 1

Here is an interesting example which tests the precedence of ** and -
and demonstrates the right to left application of **:

expr {2**-2**2} => 16

Force delayed application of -:

expr {2.0**-(2**2)} => .0625

Force left to right exponentiation:

expr {(2.0**-2)**2} => .0625

Unambiguous:

expr {(2.0)**((-2)**2)} => 16


Robert H

unread,
May 27, 2009, 9:59:12 PM5/27/09
to
Python
>>> -2**2
-4
>>>

Ruby
>> -2**2
=> -4
>>

Haskell
ghci> -2**2
-4.0
ghci>

Groovy
groovy:000> -2**2
===> -4
groovy:000>

Tcl
% expr {-2**2}
4
%

:-\


"The bottom line is that -a^b is always evaluated as -(a^b)."

source: http://mathforum.org/library/drmath/view/55709.html

tom.rmadilo

unread,
May 28, 2009, 1:36:16 AM5/28/09
to
On May 27, 6:59 pm, Robert H <sigz...@gmail.com> wrote:
> Tcl
> % expr {-2**2}
> 4
> >
> "The bottom line is that -a^b is always evaluated as -(a^b)."


Hmmm, the bottom line seems to indicate otherwise.

I guess I should point out that in python:

>>> 0-3/4
0

>>> 2**-2**2
0.0625

Which is strange. In Tcl,

expr {2**-(2**2)} => 0

For some reason python doesn't use integer math as expected. That
really sucks. Glad I don't use python.

Arjen Markus

unread,
May 28, 2009, 2:49:32 AM5/28/09
to

So, in Python sometimes integer maths is used consistently and in
other
cases it is not? That is bad, indeed!

Regards,

Arjen

dkf

unread,
May 28, 2009, 6:29:19 AM5/28/09
to
On 27 May, 21:59, Robert H <sigz...@gmail.com> wrote:
> >>> -2**2
> -4

So it's not interpreting the "-2" as a value? Fascinating, if stupid
and inefficient.

Donal.

Larry W. Virden

unread,
May 28, 2009, 7:25:00 AM5/28/09
to
On May 27, 9:59 pm, Robert H <sigz...@gmail.com> wrote:
> Python
>
> >>> -2**2
> -4
>
> Ruby
>
> >> -2**2
> => -4
>
> Haskell
> ghci> -2**2
> -4.0
> ghci>
>
> Groovy
> groovy:000> -2**2
> ===> -4
> groovy:000>
>

Perl
print "-2**2 . "\n";
-4

Gawk
{ print -2**2; }
-4

However, at least on my Solaris 9 machine

Bc
-2^2
4


SimonG

unread,
May 28, 2009, 9:36:49 AM5/28/09
to


I have just tried the following:

% expr {-2**2 + 1}
5
% expr {1 - 2**2}
-3
% proc v1 {x} {
return [expr {1 - $x**2}]
}
% proc v2 {x} {
return [expr {-$x**2 + 1}]
}
% v1 2
-3
% v2 2
5

This seems to me to be incorrect. Is there any scope for changing it
in 8.6 ?

Simon Geard

RHS

unread,
May 28, 2009, 10:52:10 AM5/28/09
to

That's pretty much the entire discussion of the thread; whether it's
incorrect or not. Its a somewhat arbitrary decision, based on what
makes the most sense for the most people... rather than a law of
mathmatics.

In sexpr, does "-2**2" get parsed as:
(power -2 2)
or
(- (power 2 2)

Personally, I prefer the former, since it requires the least amount of
typing in the long term...
- the former requires adding parens around an expression when you want
to negate it
- the later requires putting parens around a number when you want to
negate it

I negate numbers far more often than I negate expressions.

Robert H

unread,
May 28, 2009, 1:12:16 PM5/28/09
to

That "bottom line" quote is from the math link, not from me.

AngaloPapeteri

unread,
May 28, 2009, 5:52:14 PM5/28/09
to
On May 28, 7:36 am, "tom.rmadilo" <tom.rmad...@gmail.com> wrote:
> I guess I should point out that in python:
>
> >>> 0-3/4
>
> 0
>
Yes, this is a well-known historical error of Python, and one which
has been fixed in Python 3.0:

$ python3.0
Python 3.0.1 (r301:69556, May 22 2009, 11:34:35)
[GCC 4.0.1 (Apple Inc. build 5490)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 0-3/4
-0.75

Also note that it's possible to have (/) behave sanely by importing
the correct division operator from __future__ in Python pre-3.0:

$ python
Python 2.5.1 (r251:54863, Feb 6 2009, 19:02:12)
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 3/4
0
>>> from __future__ import division
>>> 3/4
0.75

AngaloPapeteri

unread,
May 28, 2009, 5:56:11 PM5/28/09
to

What's inefficient about it? And why would "-2" be a value rather than
a unary operator applied to a value? And as far as "stupid" goes, it
behaves the same way mathematics do (where exponent binds tighter than
the negative prefix operator) and as Robert H showed it also behaves
the way most programming languages (with an exponent operator) do.

AngaloPapeteri

unread,
May 28, 2009, 5:56:42 PM5/28/09
to
On May 28, 12:29 pm, dkf <donal.k.fell...@man.ac.uk> wrote:

What's inefficient about it? And why would "-2" be a value rather than

SimonG

unread,
May 28, 2009, 6:20:52 PM5/28/09
to


... and on my Linux machine. For tcl I think that if you use mathop
the current behaviour is more understandable:

% namespace import ::tcl::mathop::*
% ** -2 2
4
% - [** 2 2]
-4

Having said that I would suggest that the current behaviour for expr
is wrong and the results generated by Fortran are correct:

! Fortran program to illustrate parsing of ** and unary -
program parseInts
implicit none
integer :: i, v1, v2, v3

v1(i) = 1 - i**2
v2(i) = - i**2 + 1
v3(i) = 0 - i**2 + 1

write(*,'(a)') ' i v1(i) v2(i) v3(i)'
do i = -2,2
write(*,'(i2,3(a,i2))') i,' ',v1(i),' ',v2(i),' ',v3
(i)
end do
end program parseInts

g95 -o parseInts parseInts.f90
./parseInts
i v1(i) v2(i) v3(i)
-2 -3 -3 -3
-1 0 0 0
0 1 1 1
1 0 0 0
2 -3 -3 -3


Compared to

# Tcl program to illustrate parsing of ** and unary -
proc v1 {i} {
return [expr {1 - $i**2}]
}

proc v2 {i} {
return [expr {- $i**2 + 1}]
}

proc v3 {i} {
return [expr {0 - $i**2 + 1}]
}

puts " i v1(i) v2(i) v3(i)"
for {set i -2} {$i <= 2} {incr i} {
puts -nonewline "[format %2d $i] "
puts -nonewline "[format %2d [v1 $i]] "
puts -nonewline "[format %2d [v2 $i]] "
puts "[format %2d [v3 $i]]"
}

tclsh8.5 parseInts.tcl
i v1(i) v2(i) v3(i)
-2 -3 5 -3
-1 0 2 0
0 1 1 1
1 0 2 0
2 -3 5 -3


Simon

suchenwi

unread,
May 29, 2009, 3:07:57 AM5/29/09
to
On 28 Mai, 23:56, AngaloPapeteri <maskl...@gmail.com> wrote:
> On May 28, 12:29 pm, dkf <donal.k.fell...@man.ac.uk> wrote:
> > On 27 May, 21:59, Robert H <sigz...@gmail.com> wrote:
> > > >>> -2**2
> > > -4
> > So it's not interpreting the "-2" as a value? Fascinating, if stupid
> > and inefficient.
> What's inefficient about it? And why would "-2" be a value rather than
> a unary operator applied to a value?

What is the resulting value of applying unary - to 2?
-2
The ambiguity is that "-" is both an operator as well as part of the
alphabet of numeric constants. APL distinguished -2 and _2 (the latter
for the value -2), but I don't think other languages will (or should)
hop on that train...

dkf

unread,
May 29, 2009, 7:05:21 AM5/29/09
to
On 29 May, 03:07, suchenwi <richard.suchenwirth-

bauersa...@siemens.com> wrote:
> The ambiguity is that "-" is both an operator as well as part of the
> alphabet of numeric constants. APL distinguished -2 and _2 (the latter
> for the value -2), but I don't think other languages will (or should)
> hop on that train...

Standard ML writes unary negation with the ~ character, which has the
effect of making the grammar unambiguous.
http://www.rosettacode.org/wiki/Basic_integer_arithmetic#Standard_ML
(OTOH, it does mean that bitwise inversion is not a basic operator.)

Donal.

0 new messages