5 ms·
I was just about to laugh at JS, when I realized you can do the exact same thing in Java also. a.equals(1) && a.equals(2) && a.equals(3) can evaluate to true, i
by whack 9y ago
I was just about to laugh at JS, when I realized you can do the exact same thing in Java also. a.equals(1) && a.equals(2) && a.equals(3) can evaluate to true, if you overload the equals method with a particularly dumb interpretation. I believe the same principle will also apply to any language that supports operator overloading, such as C++.
- compsciphd 9y agoand a particularly dumb interpretation can be return true
- jerf 9y agoYes, while it may be fun to change values in a careful way, this is by far the more interesting one. The equivalent of "return true" is so powerful (or, alternatively, is so parsimonious in its use of power, depending on your perspective), you can even make it work in Haskell, where these mutation tricks don't work, because you can declare a newtype with a custom declaration of == that is just "true".
- kodablah 9y agoEven if you were using the [identity] equality operator in Java, since the question asks if it could "ever evaluate to true", the answer is also yes if another thread is updating the var during the if check.
- _nalply 9y agoThis could perhaps happen within async functions when you have await's interleaving. Or in server-side Meteor code because of fibers. But not in the browser in non-async functions because JavaScript is single-threaded, especially inside a compound expression.
- anfractuosity 9y agoJust tried it in C with a thread, which did work like you say. int a = 1; void *brute(void *vargp){ while(1) { a = 1; a = 2; a = 3; } } int main(){ pthread_t tid; pthread_create(&tid, NULL, brute, NULL); while(1){ if( a == 1 && a == 2 && a == 3 ){ printf("woo\n"); return; }else{ printf("fail\n"); } } }
- zethraeus 9y agoThis is a good answer to the terrible question. Nice.
- Bootvis 9y agoArguably C++ is worse: class Equal { public: template <typename T> bool operator==(const T& eq) { return true; }; All kinds of equality are possible.
- labster 9y agoIn Perl 6, we can do much the same without all of the boilerplate. class a {}; multi sub infix:<==> (a $a, $b) { True } if a == 1 && a == 2 && a == 3 { say "true!" } If you wanted to make an actual iterator out of `a`, you could do: multi sub infix:<==> (a $a, $b) { ++(state $) == $b } In that case, `a` would equal 1, 2, and 3 in that order. 5 is right out.
- perlgeek 9y agoOr you could just use a junction: my \a = any(1, 2, 3); if ( a == 1 && a == 2 && a == 3 ) { say "OMG quantum superposition!!!"; } For those wondering what's going on: https://docs.perl6.org/type/Junction.html https://docs.perl6.org/type/Junction.html :-)
- paulirwin 9y agoIt's also trivial in C# to overload the == operator. The following works in C# Interactive (the Visual Studio REPL). class A { public static bool operator ==(A a, int b) => true; public static bool operator !=(A a, int b) => false; } var a = new A(); if (a == 1 && a == 2 && a == 3) Console.WriteLine("This works");
- contravariant 9y agoThe only thing bad about that is that there's no check whether equality is symmetric. As written it does make sense if you interpret it as "<=" or ">=".
- alanfranzoni 9y agoSure, but it's clear that you're overriding a method. In Js you're using an operator for which there's no explicit overloading, and instead you're exploiting 'coercion' rules.
- deleted 9y ago[deleted]
- BearGoesChirp 9y agoShould be pretty easy to do in C# as well. private int _a; public int a { get { _a++; return _a;}}
- chongli 9y agoYou can write a type in Haskell with your own crazy instance of Eq but you can't hide the mutation from the user without something like unsafePerformIO.
- inopinatus 9y agoAlso likely to apply in any late-bound language where operators are implemented by messaging e.g. Ruby: a = Object.new; def a.==(b); true; end now a == b returns true for all b.
- bunderbunder 9y agoThe more worrisome thing about equality in Java is that there are integer values for which a == a is true, while a + 1 == a + 1 evaluates to false. (edit: precision)
- deleted 9y ago[deleted]
- jcdavis 9y agoI assume you are referring to the java.lang.Integer box caching situation, which is indeed shitty. However as you've written it, that will always evaluate to true, as it unboxes, adds 1 to each side, and compares the int values, not the references. To get what I assume you are talking about, you need something like: Integer b = a+1; Integer c = a+1; b==c Which by default returns true for a=126 but false for a=127. A bad situation for sure, but thankfully pretty much every static analysis tool will spot that.
- bunderbunder 9y agoYes, you're right. Thanks for correction.
- mkup 9y agoin a pure C, without operator overloading and threads: int aa = 0; #define a (++aa) if(a == 1 && a == 2 && a == 3) { printf("pff"); }
- anfractuosity 9y agoHeh nice, that's clever.
- justinjlynn 9y agoit's essentially an explicitly clocked data race. evil.
- Sharlin 9y agoHeh, my knee-jerk reaction was to complain that that's undefined behavior but for once it's not! The logical operators && and || are defined to establish sequence points due to their short-circuiting evaluation.
- adrianratnapala 9y agoWell done. Whileone forgets evil macros are, we often forget how versatile they are in that cause. That said, I feel that in practice I have to worry more about this strange hidden behaviour in C++ and Python than in C and JavaScript. And even Python is not so bad if you stick to the standard libraries.
- chias 9y agoUntil you start playing with ctypes, where you can change the values of constants. In Python 3: >>> import ctypes >>> ctypes.memmove(id(5)+24, id(23)+24, 8) >>> 2 2 >>> 3 3 >>> 2 + 3 23 Or, similarly for Python 2 >>> import ctypes >>> ctypes.cast(id(4),ctypes.POINTER(ctypes.c_int))[4]=5 >>> 2 2 >>> 2 + 2 5
- zeveb 9y agoHere's a Common Lisp version: (let ((b 0)) (symbol-macrolet ((a (incf b))) (and (= a 1) (= a 2) (= a 3)))) For those not familiar with them, symbol macros let a symbol be expanded to an arbitrary expression, kinda like a clean version of the C preprocessor.
- deleted 9y ago[deleted]
- dumbfounder 9y agoThe question doesn't use a.equals(1) it is a==1 which is not the same and does not use the equals() method in Java, so it can't be overridden. It compares primitives or variable references only. However, it is possible for that statement to evaluate to true with threads if you manipulate the a at the right times.