10 ms·
Nerdsniping: A glimpse into a stubborn mind
- tatalegma 12y ago"I want my code to execute if port is 80 or 443, and http is false" Couldn't you simply do this?: if ((a==='80'||b==='443') && http===false) { ... }
- cowsandmilk 12y agoI think the goal was if (a==='80' || (b==='443'&&http===false)) {...}
- ssharp 12y agoI think you're right, but it's funny that both the code and the written explanation do not make that clear. Missing parenthesis in one case and missing comma in the other. I feel like I tend to use parenthesis when they are not required, but I err on the side of caution and I think it makes things more readable.
- blt 12y agoI use a lot of unneeded parentheses. Makes the intent of the program clear. If the expression gets ugly, factor out subexpressions into boolean variables. If you are depending on short circuiting to avoid computing costly subexpresions, make the dependency explicit with a nested `if`. I had a thought the other day: Complicated code should look complicated. Don't try to hide your convoluted logic. In the end, someone will have to mentally unpack it into the multi-line verbose version to understand it anyway.
- methodover 12y agoThat's an excellent thought. I feel like programmers too often try to make something complicated "pretty" -- but really this just usually has the effect of making it that much more difficult to understand.
- mox1 12y agoEither way, it's called "Boolean Logic" and as far as I knew every Computer Scientist had to take this class in college...Not sure how you could get a job as a programmer without understanding that...
- romanovcode 12y agoI was working with this guy - he always tried to prove that everything is possible wasting time. He ALWAYS over-complicated simple things. He was horrible to work with and everyone hated him. Not to say you are just like him etc. but this post reminded me of him because it was probably exactly what he would do.
- kbenson 12y agoWasting other people's time is a negative, but deepening your understanding of a topic by examining edge cases is generally worthwhile, IMHO.
- spenuke 12y agoIs it really fair to call poor code an edge case? If not for the double-equals typo, which most code reviews would fix, this wouldn't work. I'm more interested that this team has conversations where person A asks a really simple question that should be able to be tested in 11 seconds, person B gives a patently false answer that mistakes && for ||, which is the very thing person A is asking about. Meanwhile person C goes and spends 11 days looking for a loophole and writing a blog about it. As a person gearing up for my first web dev position, I really wonder if this is what constitutes professional Javascript development and ask myself if I shouldn't be applying to jobs already.
- kbenson 12y agoNo, person C saw an interesting question, and decided to go on an exploratory journey to see what's possible. In any job requiring mental aptitude, you'll find natural curiosity an asset, as long as you keep it within bounds. To be clear, anyone that's presented a question about a tool they are using that may pertain to it's use (be it efficiency or correctness) that shows zero interest in the answer (whether or not they have time to pursue an answer) is not someone I want to work with or manage, and should probably find another career, because the one they are in isn't holding their interest. Work doesn't have to be the most important thing to you, but if you don't like your job, the people around you WILL notice.
- scjody 12y ago> Have I learned anything directly useful? You probably haven't. But a less experienced programmer has learned why you should always use ===.
- adamman 12y agoThe example at the end of the article shows how you can have the same problem while always using ===.
- ronaldx 12y agoThe differences between programming syntax and elementary/Boolean algebra are very awkward to understand clearly and deal with correctly. We clearly understand mathematical algebra to work one way, and we naturally assume programming algebra works the same way, which it doesn't at all. Here, the antagonist says that b can't be 1 and 2 at the same time, which would be self-evident in mathematical algebra, but turns out to be quite irrelevant to Javascript and to programming paradigms generally (since two statements will never be checked simultaneously). This difference in how syntax is understood actually presents a barrier to programming for modestly trained mathematicians, who would otherwise be expected to excel.
- nmrm 12y ago>This difference in how syntax is understood actually presents a barrier to programming for modestly trained mathematicians, who would otherwise be expected to excel. Although this is true in general that syntax can be a barrier to entry, the article provides a particularly poor example. If anything, the article demonstrates how mathematical training is good preparation for many pitfalls of programming. Mathematicians are used to working with various equivalence relations, even in the same context. So if a modestly trained mathematician saw == and ===, she would immediately ask "what is the difference between these two ER's?". And then when she finds out the essential difference is that you can override ==, it would be clear that all bets are off. I can't imagine any mathematician taking more than a few minutes and a google search -- let alone 11 days -- to figure out this loophole.
- Dewie 12y ago> I can't imagine any mathematician taking more than a few minutes and a google search -- let alone 11 days -- to figure out this loophole. If anything, mathematicians are incredibly used to overloaded equals operators.
- nmrm 12y ago> If anything, mathematicians are incredibly used to overloaded equals operators. That's my point. The == sign meaning many things is unsurprising (and key to this "hack"), whereas explicitly using two different symbols for equivalence in the same expression is a huge, glaring signpost to pay attention.
- alistairjcbrown 12y ago> I guess we’ve messed with the prototype too much, and JavaScript isn’t really convinced it’s still a proper number anymore. You're comparing a literal number with an object, which are not the same type. 2 === new Number(2) // => false 2 == new Number(2) // => true
- Dewie 12y agoDefining a number to be a procedure (or 'word' in the parlance) is simple in Forth. > : a 2 ; > : 2 3 ; > a 2 = > a 3 = The two flags on the top of the stack are now equal.
- mathattack 12y agoIs this a case of readability versus theoretical perfection?
- antinitro 12y agovar i=0; var b = {}; b.valueOf = function () { return ++i: }; if (b==1 && b==2) {//success}
- gkop 12y agovar i=0; var b = {}; b.valueOf = function () { return ++i; }; if (b==1 && b==2) { console.log("success")}
- peterkelly 12y agoAnd now for exercise 2: Port the solution to Haskell
- deleted 12y ago[deleted]
- chrra 12y agonewtype X = X (IORef Int) instance Num X where fromInteger = X . unsafePerformIO . newIORef . fromInteger instance Eq X where (X a) == (X b) = unsafePerformIO $ do x <- readIORef a y <- readIORef b writeIORef a $ x+1 return $ x == y ghci> a <- fmap X $ newIORef 1 ghci> a == 1 && a == 2 True Edit: formatting.
- okasaki 12y agoeven more general: let a = 1; _ == _ = True in a == 1 && a == 2
- wambotron 12y agoI think the answer to "can something be fuzzy equal to one value and strictly equal to another in JS?" has an easy answer that doesn't take much effort to find. This might be cooler in another language, though. var b = 2; b == '2'; // true b === 2; // true
- neil_s 12y agoThis is what I was gonna say! I don't know much JS, but after @sgdesign 's recent primer, the answer to the first two conditions seems obvious, b=="2" and b===2. Herpderp is just a cop out, since you could have infinite other variables that b equals, if you set the value to the same thing!
- philip_roberts 12y agoExcept the question was b==1 && b===2
- mikeryan 12y agoI think you missed a bit of his point which was to make that exact expression evaluate as true (b == 1 && b===2 && b === herpderp)
- gyepi 12y agoNerdsniping reminds me of the Walt Whitman poem: There was a child went forth every day; And the first object he look’d upon, that object he became; And that object became part of him for the day, or a certain part of the day, or for many years, or stretching cycles of years. It's especially bad if you'd really rather be doing something other than what you're currently doing.
- cinitriqs 12y agoso... (everything == all && all == everything) == stardust/code
- mncolinlee 12y agoAnd this is why Javascript can be such an awful language. Leaving off a single equals has such a profound effect, often without a new coder even realizing it while reading the code. Imagine what happens to your code when someone tries to write a function for its side effects similar to the example seen in the blog post. Then releases it in production for it to break in six months with a feature change.
- maxbucknell 12y agoAt the end of the article, it is demonstrated that this can happen even with strict equality by overriding the getters. Any language with getter/setter support can do this. Operator overloading can be used for even nefarious ends. The point is that side effects in code are dangerous, and can be used to mislead a reader. If this happens, it is not the fault of JavaScript. Anyone who writes code like that for purposes other than demonstration or learning is a moron.
- mikeash 12y agoNot all languages with getter/setter support will invoke them automatically like this. For example, it's not possible in Java or Objective-C to make an expression of the form a == b, where a and b are plain variables, have any side effects.
- tyilo 12y agoIn Obj-C you can if you would allow `a.prop == b.prop`.
- ssdfsdf 12y agoThis took you 11 days?!
- poweribo 12y agothe classic feigned surprise
- level 12y agoCall me nitpicky, but it always bugs me when someone references some content, but doesn't link to it. Specifically the XKCD and Stackoverflow links. Link to the comic and question specifically, rather than making me go hunt for that content.
- mfonda 12y agoI think there was a more general question here that was missed: can a == x && a == y ever be true for any arbitrary values of a, x, and y, where x != y. From a logical point of view, no, this can never be true. I would suspect this can never be true in javascript, and could only be made true in a language where you can override == to always return true. I think when most developers use the word "never", what they really mean is "never (within the current context)". This makes conversations a lot simpler. Imagine how difficult conversations would be if you always had to qualify never. "This can never be true (assuming a weird valueOf method hasn't been defined and assuming I didn't modify the javascript interpreter to always return true for == and assuming ...)".
- tonyarkles 12y agoHere's a JavaScript example, based on what was in the article. var b = {c:0}; b.valueOf = function() { this.c++; return this.c; } b == 1 && b == 2 > true
- mfonda 12y agoThat only works for consecutive integers, not any arbitrary values.
- lmkg 12y agoI think there are a few cases of non-transitive equalities in JavaScript, specifically around falsey values. Part of it also has to do with whether x is the right-side input or the left-side input, because that changes type coercion rules. Aha, found one: ['0'] == 0 > true [0] == 0 > true [0] == ['0'] > false Transitivity of equality can also never be relied upon when dealing with Floating Point numbers. This is correct and unavoidable behavior, but still surprising to many developers.
- gsg 12y agoThat's not due to transitivity: ['0'] == ['0'] (and for that matter, ['0'] === ['0']) is also false. These operators compare objects for identity, not structural equality.
- tarpherder 12y agoMight not be Java but still interesting, it made me think of one of my favorite little quirks in C++: #include <cmath> //Floating point model: Strict:Precise:Fast //Will code execute float a = nanf(""); if (a == a)//S:No P:No F:Yes (do something); if (a != a)//S:Yes P:Yes F:No (do something); if (a < 0.f || a > 2.f)//S:No P:No F:Yes (do something); if (isnan(a))//S:Yes P:Yes F:Yes (do something); NaN's (Not A Number) can propagate a long way through your code, possibly reaching places where they cause real problems. When dealing with input, especially networking, one should always check for NaN's. Basically the rule with NaN's is: The comparison always returns false if any NaN is involved. But as you can see; specifying the fast model throws that out of the window. (Code was otherwise unoptimized.) In the third statement an otherwise fine check is done to make sure the value in a is sane, it doesn't get changed but its certainly not what you'd want it to be. Whole lots of fun can be had when serving this to game servers. :D
- yeahbutbut 12y agoAnd so far everyone has missed telling the poor OP how to avoid writing two equality checks... if( [80, 443].indexOf(port) !== -1 && http === false )
- skrebbel 12y agoAre you certain that that's an improvement?
- yeahbutbut 12y agoFor two options, almost certainly not ;-) For N ports, or for a port list defined from a config file however it could be. It's even nicer in python: ports = [80, 443, ...] if port in ports and http: ... Or with underscore: var ports = [80, 443, ...]; if(_(ports).contains(port) && http) { ... } Good collections make it better than manually checking the return code or checking an explicit set of port values. Also configuration > magic_nums.
- cwmma 12y agoIf( ~[80, 443].indexOf(port) && http=== false)
- vernie 12y agoYikes. I understand that companies use these posts as a form of advertising, but seeing your "application security specialist" struggling with such a basic expression gives me pause.
- aaronem 12y agoIt's not often I see an HN thread which so aptly demonstrates the exact effect under discussion.
- gcr 12y agoThis kind of abuse is also available in Python! In [3]: class TheObjectThatIsEqualToAnything(object): def __eq__(self, other): return True In [4]: x = TheObjectThatIsEqualToAnything() In [6]: x == 3 and x == 5 Out [6]: True
- Grue3 12y agoIt's not necessarily abuse. I once had to code a dummy object that supported all arithmetic operations with normal numbers and had a special comparison logic that it is never equal to itself. Then you could test if something is a number or a dummy object by comparing it to itself.
- forrestthewoods 12y agoAnd here we all are reading this post during work hours. My god, the amount of productivity lost because of that simple question in chat!
- drvortex 12y ago0.25 = 0.25 1 - 3 + 2.25 = 4 - 6 + 2.25 1^2 + 2(1)(1.5) + (1.5)^2 = (2)^2 - 2(2)(1.5) + (1.5)^2 Since a^2 - 2ab + b^2 = (a - b)^2 (1-1.5)^2 = (2-1.5)^2 1 = 2 QED.