33

let's say I have a statement

if(stack.pop() == 1 && stack.pop() == 1)

if top of stack is 0, then the second condition won't be implemented, which means it just pops one value at the top. What I want is to pop both, the top and the value after top. Is there any way to do that without using another if-else statement in it?

Abdullah Shoaib
  • 2,065
  • 2
  • 18
  • 26
user2774903
  • 325
  • 3
  • 6

5 Answers5

102
int first = stack.pop();
int second = stack.pop();
if (first == 1 && second == 1)
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • 3
    this is the most easiest way I can think of (though liking the presented power of & operator by others). This one at least can make sure that non-comment readers will bug the code. – Stefan Mar 17 '14 at 09:55
  • Maybe we can refactor the magic "1" into something with more meaning?! – Songo Mar 17 '14 at 10:11
  • The code is more clear, but also more verbose. In my opinion, everyone should know it along with davidbuzatto's answer. – Danubian Sailor Mar 17 '14 at 11:02
  • The danger is still someone else inlining the .pop() calls, inadvertently overlooking the fact that poop() is an update operator that changes state somewhere. Comments warning against this are still advisable. – Erwin Smout Mar 17 '14 at 11:13
  • 4
    I like this best, because it clearly signals to the reader that two values are popped. – David Bullock Mar 17 '14 at 11:56
  • 2
    @ErwinSmout lol `poop()` – Tyler Mar 17 '14 at 14:07
  • 2
    shit ... A typo – Erwin Smout Mar 17 '14 at 14:49
  • @ErwinSmout: inline? In Java? – Engineer2021 Mar 17 '14 at 15:58
  • I highly recommend not to "overcome" the shortcut as in davidbuzatto's answer. It is bad to read and might lead to bugs if not everything is considered. Instead use the explicit way from JB Nizet. If possible/necessary write 5 lines instead of one. This makes the code more readable and easier to debug. – Christian Wolf Mar 17 '14 at 16:20
  • My Java IDE has a featured it calls "code inlining". It automatically replaces code such as in the answer provided here, with a single line "if (stack.pop() == 1 && stack.pop() == 2)". Maybe it works only if the variables are declared final, but it does work with the effect I describe. It also works on final methods. But I should have said "inlining the variables". – Erwin Smout Mar 17 '14 at 19:30
  • This version is fragile too. It does not prevent for another developer to inline the variables. This why you should rely on `unit test` not on hope. – gontard Jul 18 '14 at 09:37
45

Use the bitwise AND operator**:

if( stack.pop() == 1 & stack.pop() == 1 )

This will force the evaluation of both sides.

** I know it by "non-short-circuiting" of logical AND, but it is indeed a bitwise operator that acts on boolean operands (documentation here).

Update: As JBNizet said in his comment below, this code is "fragile", since some developer may "correct" the operator to the short-circuit version. If you choose to use & instead of storing the values of the method calls (forcing them to run) likewise JBNizet answer, you should write a comment before your if statement.

davidbuzatto
  • 9,207
  • 1
  • 43
  • 50
  • 29
    That is extremely fragile. It's waiting for another developer in the team, or even yourself a few days later, to change the & to a && because it looks so strange to use a non-short-circuiting binary operator instead of a short-circuiting boolean operator. Using methods having side effects in conditional tests is not something I would recommend. – JB Nizet Mar 16 '14 at 17:08
  • No "non short-circuit version" may be misleading should use term "bitwise". – Grijesh Chauhan Mar 16 '14 at 17:10
  • 2
    @JBNizet He didn't say it was a good idea. – Rhys Mar 16 '14 at 17:11
  • 5
    @Ryven: And I didn't downvote. I just commented about the fragility of this answer, because I think it's important to warn the OP and future readers about it. – JB Nizet Mar 16 '14 at 17:12
  • @JBNizet Thank you for your complementation. I know that it is fragile and error prone. I will update my answer. Maybe a comment before the if block would help. – davidbuzatto Mar 16 '14 at 17:14
  • @davidbuzatto: quite frankly, using the code in my answer is much less fragile, shows the intent clearly, and doesn't need any comment to be clear and safe. – JB Nizet Mar 16 '14 at 17:15
  • one & works for me. I am gonna use it for the program that I am working on right now because it makes the codes a lot shorter. Thank you guys. You guys are the best :) – user2774903 Mar 16 '14 at 17:18
  • @JBNizet I know... I updated my answer. – davidbuzatto Mar 16 '14 at 17:21
  • 4
    when used with booleans, it's not exactly a *bitwise* operator, it's just a non-short-circuiting logical operator. – user253751 Mar 17 '14 at 05:31
  • 1
    I would just add a comment in the source code to the reader that this is really meant as it is. Also, the term "fragile" means code is very prone to break on it's own, not when someone changes the code, so I think JB Nizet is misusing the term a bit here. – eis Mar 17 '14 at 08:42
  • @JBNizet the same argument use people for not using ++i/i++ idioms, some are even abstaining from using ++ in for loops, because they have problems underestading it. Those who can't understand langauge basics should learn them before starting to program. Otherwise you'd render most of the language features useless. – Danubian Sailor Mar 17 '14 at 10:11
  • @Łukasz웃Lツ: it's not a question of understanding vs. not understanding. It's a question of using the principle of least surprise. When reading this code, the first thing which comes to mind is "we should be using `&&` here". The second thing that comes to mind is "why do we compare the same value (`stack.pop()`) with 1, twice in the if". And if we have to compare it with 1 or 2, the first change that comes to mind is `(stack.pop() == 1 || stack.pop() ==2)`. This leads to bugs if you're not very careful. If you use the code in my answer, all these bugs are avoided. – JB Nizet Mar 17 '14 at 10:56
  • @JBNizet I don't think the principle of suprise appies here. It's a question of language, what's allowed in if clause. JavaScript allowes anything, some could argue only boolean expressions should be used there. I've once had to explain very long to my collegue the code, where I've used in if boolean variable instead of expression. He couldn't understand that idiom for long. It doesn't mean they shouldn't be used. – Danubian Sailor Mar 17 '14 at 11:00
  • Using the bitwise operators on boolean seems very "fragile", or at least "suspect", too. Some IDE's issue warning against this construct, because it is "most likely a programmer typo". And it is brittle in the portability department if JVM's are free to use their own choice of bit pattern for encoding the booleans (granted, I don't know if the JVM / java language spec goes as far as to spec this level of detail - if it does, conforming implementations will not deviate). – Erwin Smout Mar 17 '14 at 11:10
  • @ErwinSmout Using these operators on booleans is well-defined in the JLS ([see here](http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.22.2)). – ntoskrnl Mar 17 '14 at 15:40
  • While the principle of least surprise is reasonable to a point, taking it to its extreme will often result in avoidance of useful features of a language that can make both coding and maintenance simpler. (One extreme example would be never using overloaded methods because "multiple methods with the same name might be too confusing", resulting in a mass of `valueOfString()`, `valueOfInteger()`, etc. methods. Or even "all non-private methods must be marked final because polymorphism can be confusing and allowing subclasses to override parent methods may result in unexpected behavior".) – JAB Mar 17 '14 at 18:32
  • @ntoskml thanks for the info (but now I'm left wondering why they even bothered to define this. It's a 100 % replica of the logical operators &&, ||, ...) – Erwin Smout Mar 17 '14 at 19:37
  • Meaning, the "non-short-circuited" evaluation isn't specced for the "bitwise" versions either. Not in the part you pointed to. – Erwin Smout Mar 17 '14 at 22:02
4

Yet another one-line and slightly obfuscated way to do this:

if( stack.pop() == 1 ? stack.pop() == 1 : stack.pop() == 1 && false )

Personally I'd go for JB Nizet's way. Makes it as clear as can be exactly what you're trying to do.

blgt
  • 8,135
  • 1
  • 25
  • 28
0

easiest, I found is (if stack only contains 0 and 1):

if(stack.pop() + stack.pop() == 2)

or JB's solution with one variable:

int first = stack.pop();
if (stack.pop() == 1 && first == 1)
Zaheer Ahmed
  • 28,160
  • 11
  • 74
  • 110
-1

Here is an approach that will bypass the EmptyStackException thrown when the stack has fewer than two elements.

if (stack.size() > 0) {
    int first = stack.pop();
    if (stack.size() > 0) {
        if (first == 1 && stack.pop() == 1) ; //do something here
    }
}
La-comadreja
  • 5,627
  • 11
  • 36
  • 64
  • 1
    This will _not_ do what the question asked about, you'd need to swap the order of the statements in the third `if`. – blgt Mar 28 '14 at 13:20