Live data from Hacker News

Weird Python Integers

kate.io

131–140 of 150 posts

Re: Weird Python Integers

#131

Earlier quoted context omitted.

Can you elaborate on this? Integer a = new Integer(2); Integer b = a; Here a == b and no comparison by value. Integer c = new Integer(2); Then a != c but a.equals(c) (in Java). My point is that I do not agree with that and would like to have a == c, which would be the case if '==' was implemented using comparison by value.

> Here a == b and no comparison by value. Um, nonsense? class Intbox { public static void main(String[] args) { Integer a = new Integer(2); Integer b = a; System.out.println(a == b); System.out.println(a.equals(b)); } } $ java Intbox true true

I believe what your parent is emphasizing the difference between comparing a == c and a == b. Both are identity comparisons as opposed to value comparisons.

    > cat intbox.java 
    class Intbox {
        public static void main(String[] args) {
            Integer a = new Integer(2);
            Integer b = a;
            Integer c = new Integer(2);
            System.out.printf("a == b => %b\n",  a == b);
            System.out.printf("a.equals(b) => %b\n",  a.equals(b));
            System.out.printf("a == c  => %b\n", a == c);
            System.out.printf("a.equals(c) => %b\n", a.equals(c));
        }
    }

    > javac intbox.java

    > java Intbox
    a == b => true
    a.equals(b) => true
    a == c  => false
    a.equals(c) => true
Edit to add: Your point regarding that "there is no way to compare equal by identity without also comparing equal by value" is true but doesn't really say much. (I'm not sure if it isn't a tautology?) There are cases where one might want to know whether two objects are the same object, or whether they represent the same value. Which you want depends on context.

That's separate from the decision Java made that == was for identity comparison. Some people disagree with that decision.

Re: Weird Python Integers

#132
post #104
post #101

Earlier quoted context omitted.

> In Java it's not confusing when you realize that == always compares values (i.e. things that can be stored in variables); it's just that for reference types, the values are references. It's still confusing. Plenty of "reference types" behave like values in all obvious senses. Why should "foo" be a reference but 45L a value?

Because "foo" is an instance of String, aka subclass of Object, while 45L is a value for the primitive type long. I fail to see the confusion, other than for newbies.

That's tautological. The question is not why String behaves as a reference type - obviously, because it is a reference type. The question is, why is String a reference type, when it has such obvious value semantics?

And it's a perfectly valid question. The real answer is that they wanted strings to have methods, so it had to be a class, because primitives can't have methods; and Java doesn't have value classes, so it had to be a reference type. So the reason is a deficiency in the language.

A better question is, why .NET string is a reference type (with overloaded == to make it behave like a value, even!). It could have easily been a struct. I suspect that this is one of those decisions that were made very early on to basically be like Java because that's what people expect; and then it became impossible to change without major breakage.

The real problem is that most implementations that do reference / value type distinction, mix up semantics and implementation. What we really need is the ability to say that something 1) doesn't have a meaningful identity, and 2) is immutable (in a sense that you can't replace individual components of that object; you still can replace the whole object). When you combine these two, you get something that can be implemented as a value type under the hood, but the programmer doesn't need to think about it. They can just continue treating it as a reference, just as they do in Python. There's no way to tell the difference.

Re: Weird Python Integers

#133
post #99

Earlier quoted context omitted.

In C++, == pretty much always uses value semantics regardless, because reference semantics are pretty much always explicit (dereference with star etc).

I think you mean reference with & (e.g. &x == &y)

No, I mean dereference if what you have are reference types (i.e. pointers in C; I'm using Java terminology here, since that's the baseline for comparison) to begin with, which is equivalent to the situation in Java. E.g. to copy the referenced object, you need to do x = y, while x = y copies the reference (pointer) itself. Similarly, when you compare, x == y compares the referenced objects, while x == y compares the references (pointers). And even for member access, you have to do (*x).foo, or the equivalent syntactic sugar x->foo.

Re: Weird Python Integers

#134
post #131

Earlier quoted context omitted.

> Here a == b and no comparison by value. Um, nonsense? class Intbox { public static void main(String[] args) { Integer a = new Integer(2); Integer b = a; System.out.println(a == b); System.out.println(a.equals(b)); } } $ java Intbox true true

I believe what your parent is emphasizing the difference between comparing a == c and a == b . Both are identity comparisons as opposed to value comparisons. > cat intbox.java class Intbox { public static void main(String[] args) { Integer a = new Integer(2); Integer b = a; Integer c = new Integer(2); System.out.printf("a == b => %b\n", a == b); System.out.printf("a.equals(b) => %b\n", a.equals(b)); System.out.printf…

The point is that equality of identity is objectively more fundamental than equality by any other metric. You can easily observe this by noting that any two objects which are equal in identity are necessarily equal in all other possible ways.

There is no argument to be made that "comparison by value is just as fundamental a concept as comparison by identity", or that this is just a matter of opinion.

The fact that it is possible to compare equal by value without comparing equal by identity does not contradict that it is impossible to compare equal by identity without also comparing equal by value, however you define "equal by value".

> Your point regarding that "there is no way to compare equal by identity without also comparing equal by value" is true but doesn't really say much. (I'm not sure if it isn't a tautology?)

It's not a tautology; it is one of three requirements defining an equivalence relation. (Equivalence relations are by definition reflexive, which is to say x is equivalent to x for all x.)

Re: Weird Python Integers

#135
post #131

Earlier quoted context omitted.

I believe what your parent is emphasizing the difference between comparing a == c and a == b . Both are identity comparisons as opposed to value comparisons. > cat intbox.java class Intbox { public static void main(String[] args) { Integer a = new Integer(2); Integer b = a; Integer c = new Integer(2); System.out.printf("a == b => %b\n", a == b); System.out.printf("a.equals(b) => %b\n", a.equals(b)); System.out.printf…

The point is that equality of identity is objectively more fundamental than equality by any other metric. You can easily observe this by noting that any two objects which are equal in identity are necessarily equal in all other possible ways. There is no argument to be made that "comparison by value is just as fundamental a concept as comparison by identity", or that this is just a matter of opinion. The fact that it…

There are contexts where object identity is meaningless, however. In mathematics, a 2 is a 2 is a 2. This 2 versus this other 2 doesn't have meaning. This can easily trip people up, and arguing that object identity is more fundamental is meaningless. In many contexts, it's the value that's important, and object references actually get in the way. The many discussions on boxed versus unboxed and value types out there are evidence of this.

I agree that in some sense you can say that "identity comparison is more fundamental that value comparison". As I added in my first comment, I think this is likely a tautology, and doesn't do much work for you at the end of the day. The important thing is keeping the two straight and doing the appropriate comparison depending on the context.

Re: Weird Python Integers

#136
post #135

Earlier quoted context omitted.

The point is that equality of identity is objectively more fundamental than equality by any other metric. You can easily observe this by noting that any two objects which are equal in identity are necessarily equal in all other possible ways. There is no argument to be made that "comparison by value is just as fundamental a concept as comparison by identity", or that this is just a matter of opinion. The fact that it…

There are contexts where object identity is meaningless, however. In mathematics, a 2 is a 2 is a 2. This 2 versus this other 2 doesn't have meaning. This can easily trip people up, and arguing that object identity is more fundamental is meaningless. In many contexts, it's the value that's important, and object references actually get in the way. The many discussions on boxed versus unboxed and value types out there…

In mathematical terms, what I'm saying is that equality is more fundamental than equivalence as defined by some other equivalence relation[1]. If you're considering integers according to their remainder when divided by 5, you can easily show that 4 is equal to 4, and that 4 is equal to -6. If you change your metric to remainder when divided by 3, you'll notice that 4 is still equal to 4, but no longer equal to -6. That is because 4 is fundamentally more similar to 4 than -6 is.

[1] And as I've already mentioned, you can see that this is true by looking at the definition of an equivalence relation. They all treat everything as equivalent to itself.

Re: Weird Python Integers

#137
post #131

Earlier quoted context omitted.

I believe what your parent is emphasizing the difference between comparing a == c and a == b . Both are identity comparisons as opposed to value comparisons. > cat intbox.java class Intbox { public static void main(String[] args) { Integer a = new Integer(2); Integer b = a; Integer c = new Integer(2); System.out.printf("a == b => %b\n", a == b); System.out.printf("a.equals(b) => %b\n", a.equals(b)); System.out.printf…

The point is that equality of identity is objectively more fundamental than equality by any other metric. You can easily observe this by noting that any two objects which are equal in identity are necessarily equal in all other possible ways. There is no argument to be made that "comparison by value is just as fundamental a concept as comparison by identity", or that this is just a matter of opinion. The fact that it…

> any two objects which are equal in identity are necessarily equal in all other possible ways

Two NaNs are equal in identity but not in value, according to the IEEE spec.

Re: Weird Python Integers

#138
post #100

For comparison, integers in clisp: [1]> (eq (expt 2 47) (expt 2 47)) T [2]> (eq (expt 2 48) (expt 2 48)) NIL Explanation here: https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node17.html

But nobody would use eq in lisp for this. For numbers you would use equal, comparing the values. You only would use eq for addresses, like cons cells or vectors. E.g. in php there is == vs ===.

re python: this is of course superlame. the compiler can easily detect "is " and forbid the const int table optimization. Only "is None" would make sense.

Re: Weird Python Integers

#139

Is there any practical reason to use "is" to compare two ints (other than demonstrating integer interning)? Should doing so produce a warning?

That depends on what your definition of "is" is.

"is" is a well defined comparison operator in Python which compares object identity. Some philosophical argument about the meaning of "is" is tangential.

Re: Weird Python Integers

#140

Earlier quoted context omitted.

You can think up an unreasonable example for anything though. If I have a graph data structure then `node == node` with identity does make sense to me in lots of cases. And what's the value equality of `(new Object()).equals(new Object())` - they have no value.

The point is that the language treats numbers as objects when they aren't. It's not that reference semantics don't have a place, it's just that the place isn't numbers. As for your second question, it looks like the type system has two embarrassing questions: what the heck does "new Object()" mean? Nothing worth saying.

I use `new Object()` in my code and I use it exactly for identity equality! If I want a unique ID for something I create a new object and it's guaranteed it will never be reference equality to any other object anyone else could construct.
Post reply on HN