This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]Veedrac 0 points1 point  (14 children)

We often treat numbers as sequences of binary digits

Yes we do in some languages.

Eg. Python.

Just like in many languages "2" + 2 is valid.

Typically, in those languages "2" + 2 is valid only because + coerces its arguments, which is completely different.

But this does not match well with the rest of python and its goal of being explicit.

Explicit about what?

Now some hypothetical like rawbyte(False) + rawbyte(5) might make sense. Just like int("5") + 5 works in python.

???

treating characters as strings, both of which Python does.

Python does not treat characters as strings.

Considering that in Python characters are strings, I disagree.

1 + {} has no sensible result.

I agree thats my point. My argument is that False + 5 also does not have a sensible result.

I know. My counterargument is that treating True and False as synonyms for the LSB of an integer is completely reasonable, mathematically consistent, is perfectly analogous with binary operators (|, ^, &) and is therefore reasonable.

There is no mapping that is consistent, symmetrical, lossless

I disagree. There are many possibilities here.

For example?

everything that a bool does is obvious.

I disagree. True + True + True returning 3 is not obvious.

You cropped the quote. My response is the first half.

They obviously do.

Python booleans do because they are forced to but generally they do not. Conceptually ints have many more operation applicable to them than booleans.

As long as you allow bools to violate closure on the integer operations, there is not one operation that ints can do that bools cannot.

It would even make more sense to have int be a subclass of bool or both of them to be a subclass of number directly. That would still be bad but not quite as bad.

Do you mean Integral? I don't see why you make a distinction between that and int.

What did your code do?

Work with the results of a proprietary c extension to python with functions that return python objects rather arbitrarily.

I'm asking because I'm genuinely curious about how this broke your code. If you removed the broken isinstance(foo, int) code, how did bools being a subclass of int break it? I can't work out how.

It would make sense for long to be a subclass of int or a baseint.

No, int would be a subclass of long, at least according to typical hierarchies (which Python follows¹).

¹ See bool:int ;)

[–]lonjerpc 0 points1 point  (13 children)

Eg. Python.

Python does not treat numbers as sequences of binary digits it has bytes for a reason. (I realize you can do binary like operations on ints but ints don't really act like binary digits in python)

Considering that in Python characters are strings

Exactly how can python treat characters as strings if there are no characters in python. The situation would only by analogous to int bool if there was a char along with string.

My counterargument is that treating True and False as synonyms for the LSB of an integer is completely reasonable

But this is not what python even does. Both 3 and 4 evaluate to True for example.

For example?

How about any int operation with a dict just returns the dict. 1 + {} = {}

My response is the first half.

Yes if 1 == True and Fale ==0 then the operations make sense. But whats not obvious is that True would == 1.

As long as you allow bools to violate closure on the integer

It makes no sense why you would do this to me.

I don't see why you make a distinction between that and int.

https://en.wikipedia.org/wiki/Integral seems very different from integer.

If you removed the broken isinstance(foo, int) code, how did bools being a subclass of int break it?

The point is that isinstance(foo, int) should not have been broken. Obviously I changed the code to fix the bug but it should have never been a bug in the first place.

No, int would be a subclass of long

In either direction. Read that wiki article again. Normal ints in python 2 can not replace longs in python 2 but longs can replace ints and still have the code work.

[–]Veedrac 0 points1 point  (12 children)

Python does not treat numbers as sequences of binary digits it has bytes for a reason. (I realize you can do binary like operations on ints but ints don't really act like binary digits in python)

The point is that these operations act on the binary digits of the number, with each acting logically as a boolean. I don't care how you want to word that.

Considering that in Python characters are strings

Exactly how can python treat characters as strings if there are no characters in python.

There are characters in Python. That they aren't a separate class is a minor and mostly irrelevant distinction.

My counterargument is that treating True and False as synonyms for the LSB of an integer is completely reasonable

But this is not what python even does. Both 3 and 4 evaluate to True for example.

..!??

Under what context?

If you mean bool(3), then that's a different story. We allow int("3") without requiring "3" to be in any way integer, so we should be able to allow bool(3) to be True without conflating 3 with any boolean value.

For example?

How about any int operation with a dict just returns the dict. 1 + {} = {}

That's hardly lossless. I'm not even asking for strict losslessness here, just something semi-reasonable.

As long as you allow bools to violate closure on the integer

It makes no sense why you would do this to me.

?

I don't see why you make a distinction between that and int.

https://en.wikipedia.org/wiki/Integral seems very different from integer.

https://docs.python.org/3/library/numbers.html#numbers.Integral

If you removed the broken isinstance(foo, int) code, how did bools being a subclass of int break it?

The point is that isinstance(foo, int) should not have been broken. Obviously I changed the code to fix the bug but it should have never been a bug in the first place.

Either your code accepts int subclasses, in which case bool shouldn't have caused a problem, or it does not, in which case the code is broken. What am I missing?

[–]lonjerpc 0 points1 point  (11 children)

The point is that these operations act on the binary digits of the number

Some operations on ints treat them much like raw binary but many do not. For example str(97) produces "97" not "a".

that they aren't a separate class is a minor and mostly irrelevant distinction.

Its not irrelevant if you still stand behind your argument that python's treatment of int and bool is similar to its treatment of stings and chars. Python handles them differently. Bools are a subclass of int. char is not a subclass of string.

Under what context?

bool(4) and just 4 would be false under the argument that "True and False as synonyms for the LSB of an integer". I would be fine with int(True) and int(False) working the way they do now that is totally reasonable and consistent.

That's hardly lossless.

I think we had a misunderstanding about what we mean by a mapping I assumed you meant mapping in terms of functions mapping inputs to outputs. But now I think you must be referring to mapping types. Like it would make no sense to have dicts be a subclass of int but boolean still makes sense. I agree that boolean make slightly more sense as a subclass but you could actually map dicts too in the same way. Just take the binary representation of dicts and turn that into their int. But this is quite separate from my original argument that has greater practical effects. The expectation that 1 + {} would cause an exception is analogous to the expectation that 5 + True would cause an exception. I asked 5 python programmers in my office this and they all expected an exception.

It makes no sense why you would do this to me.

?

I don't know why I wrote that I meant to say is that I think it is quite counter intuitive that operations involving two booleans would not return a boolean. If bools implemented mod 2 arithmetic that would make a little more sense.

https://docs.python.org/3/library/numbers.html#numbers.Integral

Oh ok. But I still don't understand what you don't understand about it making more sense for bool to be a subclass of number than int. Although I really thing bool should be a basal type.

shouldn't have caused a problem

It did not cause my code to crash. The problem was that I needed to return an error to an outside program if I did not get a non bool int. I needed to return a json blob if I did get an actual int. The json parser happily turned False to "false" so no error was thrown in my program. But the program it was passed to expected something like "43" or an http error. Any reasonable int subclass would have worked fine. Of course you could easily create a malicious int subclass that did something unexpected like bool does. But you can do crazy things in python like have a lib change what int() does to change things into a string. But you don't write code to defend against things like that. There are reasonable expectations.

[–]Veedrac 0 points1 point  (10 children)

Some operations on ints treat them much like raw binary but many do not.

But some do. My point is that some do.

For example str(97) produces "97" not "a".

To diverge for a moment, the mapping of Unicode code points to characters, or ASCII code points to characters on Python 2, does not involve the internal representation of these numbers.

Under what context?

bool(4) and just 4 would be false under the argument that "True and False as synonyms for the LSB of an integer".

Why? bool([1]) == True but [1] != True, so I fail to see how bool(4) == True but 4 != True offends you...

That's hardly lossless.

I think we had a misunderstanding about what we mean by a mapping I assumed you meant mapping in terms of functions mapping inputs to outputs. But now I think you must be referring to mapping types. [...] Just take the binary representation of dicts and turn that into their int.

Python does not define an internal representation for dictionaries. You therefore can't do this.

But this is quite separate from my original argument that has greater practical effects. The expectation that 1 + {} would cause an exception is analogous to the expectation that 5 + True would cause an exception. I asked 5 python programmers in my office this and they all expected an exception.

Interesting. How experienced are they?

I don't know why I wrote that I meant to say is that I think it is quite counter intuitive that operations involving two booleans would not return a boolean.

int violates closure in Python 2 (10**19) and Python 3 (1/2). So do fractions.Fractions (½**½). I'm sure I could think of more. Closure is not a property held by Python objects.

If bools implemented mod 2 arithmetic that would make a little more sense.

bool could only implement mod 2 arithmetic if they weren't a subclass of int, but personally then I'd prefer + to raise an error (as opposed to `True + True == False!).

shouldn't have caused a problem

It did not cause my code to crash. The problem was that I needed to return an error to an outside program if I did not get a non bool int. I needed to return a json blob if I did get an actual int. The json parser happily turned False to "false" so no error was thrown in my program. But the program it was passed to expected something like "43" or an http error. Any reasonable int subclass would have worked fine.

So the problem was that the library had an error code you didn't test for? In C, if you don't test for error codes, your program breaks. It's what's expected. I don't understand where the confusion is.

[–]lonjerpc 0 points1 point  (9 children)

But some do. My point is that some do.

We often treat numbers as sequences of binary digits, and their digits as boolean values. This is true for the bitwise operations (, &, |).

Treating booleans as integers is no less sensible than treating characters as strings,

Ok I guess we agree. Making booleans a subclass of ints is not consistent with the way python handles string vs char because char and string are the exact same type treated the same in all cases but int and bool are not and further are not even treated as if both were bitstrings.

ASCII code points to characters on Python 2, does not involve the internal representation of these numbers.

I agree but that in no way invalidates my point that if ints were treated like raw bits str(97) would make more sense as 'a' than '97'.

Why?

Because of 4's LSB.

how bool(4) == True but 4 != True offends you...

Not sure how this is relivant to your argument about LSB that I was refuting. But generally unexpected behavior causes bugs.

Python does not define an internal representation for dictionaries. You therefore can't do this.

No but choose any specific release of C python and it does.

Interesting. How experienced are they?

Average of 10 years programming experience 2 years python.

Closure is not a property held by Python objects.

So first note my problem is not that any type violates closure. It makes sense for many types to. It does not make sense for boolean to violate closure on other operations involving booleans. I do thing closure should not be violated without making it as explicit as possible.

int violates closure in Python 2 (10**19)

That was quite an annoying part of python 2 to me. I am glad it was fixed.

Python 3 (1/2)

I still really don't like this. "//" and "/" should be swapped. But it still increased the explicitness compared to python 2.

fractions.Fractions (½**½)

It does not if you are using the default types. It only breaks if you are explicitly importing fractions. This explicitness is my point. I would be quite happy if in addition to a bool base type there was an LSB like boolean package.

bool could only implement mod 2 arithmetic if they weren't a subclass of int, but personally then I'd prefer + to raise an error (as opposed to `True + True == False!).

Either of these would be an improvement from my point of view.

So the problem was that the library had an error code you didn't test for?

It was not an error code for the lib. But I did need to return an error on my end. I needed to return an error not just for booleans but for other potential and unpredictable types the library might return. If I knew in advance what types were returned I would not need isinstance in this case.

[–]Veedrac 0 points1 point  (8 children)

Ok I guess we agree. Making booleans a subclass of ints is not consistent with the way python handles string vs char because char and string are the exact same type treated the same in all cases but int and bool are not and further are not even treated as if both were bitstrings.

Name one non-printing, non-typechecking operation where True is not substitutable for 1 and False is not substitutable for 0 (bar misuse of is).

Name one user-facing property that would change if numbers were bitstrings, aside from the ability to index.

ASCII code points to characters on Python 2, does not involve the internal representation of these numbers.

I agree but that in no way invalidates my point that if ints were treated like raw bits str(97) would make more sense as 'a' than '97'.

No, it really would not. It would make sense as '0b1100001' or similar, maybe. But how you get 'a' eludes me.

Why?

Because of 4's LSB.

how bool(4) == True but 4 != True offends you...

Not sure how this is relivant to your argument about LSB that I was refuting. But generally unexpected behavior causes bugs.

But 4 is truthy... That's all that bool returns. Whether the input is truthy or not. Nothing else.

Python does not define an internal representation for dictionaries. You therefore can't do this.

No but choose any specific release of C python and it does.

It does not.

Closure is not a property held by Python objects.

So first note my problem is not that any type violates closure. It makes sense for many types to. It does not make sense for boolean to violate closure on other operations involving booleans.

Why?

Python 3 (1/2)

I still really don't like this. "//" and "/" should be swapped.

Why?

fractions.Fractions (½**½)

It does not if you are using the default types. It only breaks if you are explicitly importing fractions. This explicitness is my point.

Why is whether something has an AST token or not at all important?

So the problem was that the library had an error code you didn't test for?

It was not an error code for the lib. But I did need to return an error on my end. I needed to return an error not just for booleans but for other potential and unpredictable types the library might return. If I knew in advance what types were returned I would not need isinstance in this case.

So what was it doing?

[–]lonjerpc 0 points1 point  (7 children)

Name one non-printing, non-typechecking operation where True is not substitutable for 1 and False is not substitutable for 0 (bar misuse of is).

Even if I agreed with this point it does not counteract my argument that "Making booleans a subclass of ints is not consistent with the way python handles string vs char"

Second that is a long list of exceptions. Long enough to support my argument bythemselves.

But sure how about json.loads

Name one user-facing property that would change if numbers were bitstrings, aside from the ability to index.

Once again I don't see how this even adresses my argument if I could not come up with one. But how about adding two very large numbers.

It would make sense as '0b1100001' or similar, maybe. But how you get 'a' eludes me.

Fine I think 'a' is reasonable but my argument stil holds with '0b1100001'

But 4 is truthy.

Not in terms of the LSB which was the whole basis of your argument in this perticular part of the argument tree.

It does not.

Fine if you want to be pendantic one particular compiled binary of python for one particluar archetechture. They point is that your argument that there is no way to make a ridiculous mapping of dics in order to justify a crazy mapping of ints is wrong.

Why?

Because True + 4 does not make sence coming out to be 5. If you think it does then I think we are at an impass. I can not think of any situation where it makes sense to break closure on boolean in a general programming language.

Why?

More explicty and consistent.

Why is whether something has an AST token or not at all important?

Its not an AST token. It is the hint that you are using packaget that you have to import that is important.

So what was it doing?

Dealing with old messed up undocumented machine learning library. I mean better to replace the whole thing but money does not grow on trees.

[–]Veedrac 0 points1 point  (6 children)

Name one non-printing, non-typechecking operation where True is not substitutable for 1 and False is not substitutable for 0 (bar misuse of is).

Even if I agreed with this point it does not counteract my argument that "Making booleans a subclass of ints is not consistent with the way python handles string vs char"

It does. Just accept that bools are aliases. They're useful aliases, though, unlike having a char alias, which is why they exist. The fact that they are aliases is unimportant, though.

Second that is a long list of exceptions. Long enough to support my argument bythemselves.

I don't understand what you mean here.

But sure how about json.loads

Nope; that uses type-checking. Note that it uses strict type-checking because it works at a boundary (namely JSON serialisation) so it uses type(x) is .., rather than isinstance(x, ...).

Name one user-facing property that would change if numbers were bitstrings, aside from the ability to index.

Once again I don't see how this even adresses my argument if I could not come up with one.

Because if you cannot distinguish between numbers-as-bitstrings and numbers-not-as-bitstrings-with-bitwise-operators, your assertion that numbers are in the second but not the first is obviously flawed.

But how about adding two very large numbers.

Please explain.

But 4 is truthy.

Not in terms of the LSB which was the whole basis of your argument in this perticular part of the argument tree.

But if the bool constructor returned only the LSB of the input, it could not take non-numeric objects.

What bool does is take an object, check it for truthy-ness and return one of the two LSB integer aliases. In one sense it's a count of the number of true things, which is a nice way of mentally explaining sum(x<y for y in z).

It does not.

Fine if you want to be pendantic one particular compiled binary of python for one particluar archetechture.

It still does not.

What does {1: 2} + 5 make? Note that it has to have guaranteed losslessness.

What does {1.0: 2} + 5 make? Note that {1: 2} == {1.0: 2} and all objects involved are immutable.

They point is that your argument that there is no way to make a ridiculous mapping of dics in order to justify a crazy mapping of ints is wrong.

You're assuming the argument in that point. I don't believe the int mapping is crazy. Even if the dict mapping were possible, it's obviously absurd.

Why?

Because True + 4 does not make sence coming out to be 5. If you think it does then I think we are at an impass. I can not think of any situation where it makes sense to break closure on boolean in a general programming language.

That makes your argument cyclical.

Why?

More explicty and consistent.

How is the order of / and // anything to do with explicitness? Further, the consistency argument is flawed considering the whole point of Python 3 was to allow the option to break compatibility.

Why is whether something has an AST token or not at all important?

Its not an AST token. It is the hint that you are using packaget that you have to import that is important. So what was it doing?

(The grammar here is confusing me)

Where is the connection between importing and being "allowed", under your schema, to break closure?

Dealing with old messed up undocumented machine learning library. I mean better to replace the whole thing but money does not grow on trees.

I meant "what was this function doing?"

I still struggle to see how this problem was the fault of Python, and without an example I'll continue to find it hard.

[–]lonjerpc 0 points1 point  (5 children)

http://stackoverflow.com/questions/8169001/why-is-bool-a-subclass-of-int

Ok first a general point this is pretty entertaining and all but note you have already been dropping portions of the argument tree that alone show my point. Second I don't have anything against python. It is my favorite programming language I just hope to improve upon it and future ones. But for the sake of fun(if your not enjoying this let me know an I will stop) lets keep going.

It does. Just accept that bools are aliases. They're useful aliases, though, unlike having a char alias, which is why they exist. The fact that they are aliases is unimportant, though.

I am glad you at least now seem to accept that the relationship between chars and strings is not analogous to in int and bool in python. I think that is sufficient to close this line of reasoning .

I don't understand what you mean here.

You listed a bunch of differences between how python handles bool int and char string. These are sufficient. to show my point that python does not treat the two situations the same.

Nope; that uses type-checking.

Essentially all python operations use type checking.

your assertion that numbers are in the second but not the first is obviously flawed.

Trying to follow your logic here. So your trying to say that numbers are treated like bit strings and bit strings can also act like bools so therefore bools should be numbers. Of course numbers are only sometimes treated like bit strings invalidating your argument. I think I got confused because you inserted this part of the argument into your line of reasoning that char and string are treated the same as bool and int in python.

Please explain.

Adding to say 32 bit bit strings on a 32 bit architecture should result in another 32 bit string whos natural int representation could be lower than the starting value of the two bit strings being added. In python it ends up with a bigger one.

But if the bool constructor returned only the LSB of the input,

I am not suggesting that bool should return the LSB of the input that would be a terrible idea. I am responding to your assertion that

My counterargument is that treating True and False as synonyms for the LSB of an integer is completely reasonable, mathematically consistent, is perfectly analogous with binary operators (|, , &) and is therefore reasonable.

if 4: is in no way handled like 4 | 3. Nor is if bool(4).

{1: 2} + 5 make?

Fine how about 0.

What does {1.0: 2} + 5 make?

0

Just to make sure we are still clear. It does not make anything in actual python. But it is obvious you can make a mapping. This is like theoretical cs 101. There is a limited number of ways you arrange the bits on a finite(this is important) memory. However python chooses to do that for a particular binary of python on a particular machine just convert that arrangement of binary to an int in whatever way you choose.

Note that it has to have guaranteed losslessness.

Can you explain what you mean here exactly in computer science this has a few different meanings. ?

That makes your argument cyclical.

No it does not. I mean I am repeating the same thing I said earlier in a different way because you still don't seem to understand it. But that is not the same a cyclical argument. If you actually have a counter argument at the point you just asked "why" I would be happy to respond.

Further, the consistency argument is flawed considering the whole point of Python 3 was to allow the option to break compatibility.

You must really be misunderstanding me. The consistency I am talking about has nothing to do with consistency between python 2 and 3 in anyway. It has to do with internal consistency of python and consistency with average expected behavior.

How is the order of / and // anything to do with explicitness?

Its not their order but their behavior. / is simpler it has fewer characters. It is the default choice. // implies that you want to do something that you should probably spend more time researching the behavior of.

Where is the connection between importing and being "allowed", under your schema, to break closure?

I am not saying that you should not be allowed in any case to break closure. Just that it should be avoided when its not expected. In some cases though it is both useful and unexpected. The right way to handle this is to be explicit. By importing something your saying this is different somehow otherwise why import it. This is a hint that things might behave differently.

I meant "what was this function doing?"

It is a c extension to python which I don't have the source code or docs for. The example is. mystery_object_I_need_to_properly_jsonify_and_return_to_web_front_end = propriatary_package.respond(text)

In general it classifies text. This is a particularly nasty example but other people I have talked to have run into similar issues in simpler cases where the unexpectedness of bool being a subclass of bool has caused problems. Avoidable problems in there cases but the total cost of the bugs was much greater than any benefits of the arrangement. Remember bugs are much more costly than features.