[Tutor] writer overloaded

Avi Gross avigross at verizon.net
Wed Nov 28 21:04:36 EST 2018


Steve,

I read your reply in which you address selected parts of my earlier message. I conclude I am either not writing as clearly as I hoped or your interpretation is sometimes not what I intend. And, I can also be wrong or incomplete!

I won't reply in-line or comment much on what I accept or agree with. Your comment about a good reason for the change in error handling makes perfect sense. But it relates to what I said in a way. The sequence of values allowed is a tuple of any length but it there are two or more, it gets ambiguous whether the last one is a special one used as a variable name you assign the particular error to or yet another kind of error. Adding "as" changes the syntax to "tuple [as name]" which is unambiguous and also allows "name" to be a reuse of a name that might otherwise happen to be an Error that wouldn't happen in this context but does exist.

My focus is on what I said about Mathematics. I have very specific approaches to what I mean by mathematics and it is a very broad field with many seemingly different kinds which may overlap on careful study but which can each have their own use of concepts and symbols. Yes, mathematics as in routine algebra and geometry has a fairly serious focus on equality, often tautology, especially in higher and more abstract forms as when making proofs step by step. There are related concepts like congruence where you might not use an equals sign or inequalities where you use variants like <=.

When a mathematician wants to SET a variable to a value, they often say things like:

Given:

Y = 5

Or
Let Y = 5 when X = 10 be the sides of a rectangle then the Area = X*Y

Or other phrases like "assuming" where the meaning remains that the combined expression on either side of the equals sign evaluates to the same thing.

(X+1)*(X-1) = X^2 - 1

literally tells you there are at least two ways to say something that are the same no matter what X is.

tan(x) =- sin(x)/cos(x) 

Is the same idea but maybe not exactly for the reason you mention that you can calculate it that way.

The definition of the sin(x) is based on a Euclidean right triangle where you have two other angles that are not 90 degrees (or pi/2 radians) and you pick one of those angles and call it x. For each such angle, there are two sides of the triangle that delineate the angle with one being called the "hypotenuse" (the longest one) and one being called "adjacent". I know this is very basic geometry trending into trigonometry but trying to be very clear here. The third side sort of "opposite" the angle is called that.

Now the definition of sin(x) is the ratio of opposite/hypotenuse. When the angle is 0, there is no triangle, As it opens up wider toward 90 degrees, the ratio climbs from 0 to as high as 1, asymptotically. At the same time as the opposite side lengthens, the adjacent side gets smaller and the cos(x) is defined as adjacent/hypotenuse and moves from 1 down towards 0. 

If you define the tangent as opposite/adjacent, it can go towards plus and minus infinity but someone can show that the ratio of:

sin(x)/cos(x) = (opposite/hypotenuse)/(adjacent/hypotenuse)

the latter part can be converted from a division to a multiplication by using the reciprocal and other allowed mathematical conversions in the context of this algebra.
	=  opposite/hypotenuse * hypotenuse/ adjacent
	= (opposite*hypotenuse)/(adjacent*hypotenuse)
	= (opposite/adjacent)*(hypotenuse/hypotenuse)
	= (opposite/adjacent) + 1
	= opposite/adjacent
	= tan(x)

There are many details in the proof above, or similar ones like when you are allowed to use associative or commutative laws because the real numbers over the operators of addition and multiplication form a ring which has been proven to allow the steps above but you get the idea.

So, yes, one of many ways to calculate a tangent is to use the sine or cosine for a particular known angle but there are deeper ways such as evaluating enough terms of the right infinite series.

I repeat. In most of mathematics "=" means they are equal or assumed to be equal with any assignment taking place sort of off stage. Feel free to disagree on what may be a mostly philosophical point but that is why many places in mathematics do not feel a need for a second operator.

I am trying to keep this as "text" since the mailing list does not tolerate rich formats so it is harder to illustrate. But there are mathematical operators that make provisional assignments possible. The upside-down A can be used to mean "for all x" and the backwards E can mean "there exists an x" and there are ways to specify conditions and intended results and so on. So yes, Mathematics as a whole can say the kind of things you want. But generally the way you might say to do something to x and store the results is to introduce a different variable such as x' and then x''.

Programming languages definitely need a way to rebind but you could write perfectly usable code like this:

x = 5
temp = x
x = temp^2 +2*temp +1

The above would still rebind x but would not show it having two different values at  the same time, seemingly on the same line. But, as long as you understand precedence rule or use lots of parantheses, it is clear that everything to the left of the equals sort of happens first. Mind you, the right side can be complex and take a while to evaluate to an object such as:

a.b()["key1"]["key2"][5] = a

a might have a method called b which returns a dictionary whose entry for key1 is yet another dictionary whose result is a list whose sixth entry you want to set to point back to what a is or is it was?

And as noted, in languages that support pre as well as post autoincrement operators, you might need multiple temp variables to do the equivalent of:

while (*p++ == *++q) ;

bad example as python hides pointers so how about something else python does not support 😊

x++ = --y

Your point about peano arithmetic is indeed valid. There are many places where you can indeed have something that looks nonsensical still have valid solutions and even an infinite number of such solutions. 

x = (x + 5) mod N

is sort of what you meant. And I don't see what that disproves much as it involves a new operator. Both standard mathematics and python would see that as valid. In your example, both x are the same. I mean the same each time you try a new solution, not always the same.

Similarly, asking what angle has a particular sine value has an infinite number of answers as adding or subtracting any integral multiple of 360 degrees (or 2*pi radians) gives you the same result. That is partially because this is in a sense peano arithmetic mod 360. 😊

The mathematical definition of "=" in such cases is not really different. Any of the valid answers is equal to the result, although for some purposes, you want the lowest positive answer meaning between 0 and 360.

And the result is in a context. Complex numbers are hard to visualize but they are often the solutions to quadratic or higher-order equations. Without that context, you say there are no solutions, or at least two fewer if they are complex conjugates. 

If the two roots of an equation are:
x=5 OR x=6

There is no contradiction. Two cases are being examined. X is at times one and at times another, but never both at the same time.

You are quibbling about what I mean about the python "is" statement. Yes, it is an identity test but I repeat. I stand by my statement. It is about pointers or memory locations being compared for absolute equality. Does the first variable or expression refer to or point to the same location in memory as the second. I gave examples of how python when trying to use less memory interferes by making two different objects share the same area of memory in some cases when they are deemed immutable. It may not matter then but if your code depends on them not being seen as equal, you may have to do weird things like making them into objects that may internally point to the same string or number but then ask if object A is object B and then they are not.

When discussing whether the absolute values of two things are the same, you are saying something different than whether the two things are the same. Similar the length/magnitude of two vectors (in the mathematical sense of the square root of the sum of the squares denoting a distance from a multi-dimensional origin in N-space) can be equal even if the two vectors share no components. The address of an object is another such function and "is" generally seems to be testing the current address, sort of. There may well be exceptions.

I stand by my overall point. There are MANY ways people compare things for equality and some have subtle nuances. If this were something like C where pointers are commonly used then

p == q

and 

*p == *q

Have related but different meanings. If p points to the first 'l' (el) in "hello world" and so does q then both statements are true. If you move q to point to the second or third letter 'l' while leaving p in place, then only *p == *q is true. If q points to any non-'l' character in the same string or anywhere else where the byte pointed to (pre-unicode) does not have the same eight bits in the same order, then both of the above are false.

In python they hide pointers but they are probably there in many of the underlying implementations, albeit some use other techniques with name spaces and dictionaries. And who knows what else.

So in many cases, "p is q" means identity in a pointer way or memory location way. But clearly there can be exceptions such as evaluating p searches in one namespace and evaluating q in another, so they may not be deemed to be identical and actually aren't.

You may have also missed my last point. Short circuit evaluation is old. That is not what I consider unusual in python. What I found to be different (and it is possible other languages had or now have it) is that it does not bother jumping into a mathematical Boolean mode. That is deferred indefinitely as not important. The result of quite a few operations is neither True nor False but just about ANYTHING. To explicitly make it force a Boolean result you need to call bool(A or B and not C) which otherwise simply return A or B or C, whatever they are and the truthiness of it is determined by either it having a length of zero, or being numerically 0 or whatever the __nonzero__ (pre 3.X) or __bool__ methods for that object return, perhaps recursively if they return another object.

It turns out, mathematically, to be valid and work in an amazing number of contexts and even where it might not, you can probably use the __bool__ method to make something that works. 

Sorry to be this long. I could have summed up my entire previous message in a few sentences but then you might have said I was too broad and showed no reasons or examples. As I said, life is short.

-----Original Message-----
From: Tutor <tutor-bounces+avigross=verizon.net at python.org> On Behalf Of Steven D'Aprano
Sent: Wednesday, November 28, 2018 6:15 PM
To: tutor at python.org
Subject: Re: [Tutor] user overloaded

On Wed, Nov 28, 2018 at 12:56:32PM -0500, Avi Gross wrote:

> try ...
> except ValueError, e:
> ...
> 
> You now need to do this format:
> 
> try ...
> except ValueError as e:
> ...
> 
> Why the change?

Because the first form was a trap and a bug magnet:

try:
    block
except TypeError, ValueError, KeyError:
    print "surprise! this will not catch key errors!"



[...]
> Back to your topic. "=" as a symbol has been used over the years in 
> many ways.  In normal mathematics, it is mostly seen as a comparison 
> operator as in tan(x) = sin(x)/cos(x)

That's not a comparison, that's an identity. The tangent function is (or at least can be) defined as sine divided by cosine.


> Many programming languages used it instead to sort of mean MAKE EQUALS.

That's usually called "assignment" or "binding".


> x = x + 5
> 
> is an example where it makes no mathematical sense. How can a number be
> equal to itself when 5 is added? 

There is no solution there in the normal real number system, but there 
are forms of arithmetic where it does, e.g. "clock arithmetic". If your 
clock only has values 0 through 4, then adding 5 to any x will give you 
x back again.

Although normally we write "congruent" rather than "equals" for clock 
arithmetic: 

    x ≡ x + 5 (mod 5)


In any case, just because there is no solution doesn't mean that the 
question makes no sense:

x = x*5

makes perfect sense and has solution 0. Likewise:

x = x**2 + k

makes perfect sense too, and can have zero, one or two solutions 
depending on the value of k.



> The meaning clearly is something like x
> gets assigned a value by evaluating the current value of x and adding 5 to
> that. When done, the old value of x is gone and it has a new value.
> 
> For this reason, some languages like PASCAL used := so the above became 
> 
> x := x + 5
> 
> Yes, same symbol we are discussing and NOT what Python intends.

Actually, it is precisely what Python intends, except for two minor 
differences:

1. in Pascal, := assignment is a statement, not an expression, 
   while in Python it will be an expresion;

2. Python will discourage people from using the := expression
   form as a de facto statement, where = will do.


[...]
> And there are forms of equality that some languages need to distinguish.
> What does it mean if two (unordered) sets are equal? Must they be two
> reference to the same set or is it shorthand for them being strict subsets
> of each other in both directions? You can come up with additional
> abstractions like whether a list is a shallow or deep copy of another and
> how it effects your ideas about them being equal. You may want a way to say
> things are approximately equal. In math, something like ~= is used. Python
> has an operator called "is" that can be a variant on equality.

The "is" operator is in no way, shape or form an equality test. It is an 
*identity* test, which returns True if and only if the two operands are 
the same object.

Equality does not imply identity:

py> x = []
py> (x == []) and (x is not [])
True


nor does identity imply equality:

py> NAN = float(NAN)
py> (NAN is NAN) and (NAN != NAN)
True

Anyone using "is" when then test for equality is programming in a state 
of sin.


> Consider the concept of OR. Some languages spell it out when used in a
> Boolean context. 
> 
> a or b
> 
> But python does something new with this. In some contexts the above
> effectively becomes an IF.

This is called a "short-circuiting boolean operator", and it was old, 
old old when Python started using it 25+ years ago. I believe Lisp was 
the first to introduce them, in the 1950s.

https://en.wikipedia.org/wiki/Short-circuit_evaluation



-- 
Steve
_______________________________________________
Tutor maillist  -  Tutor at python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor



More information about the Tutor mailing list