Page 1 of 2

ANDs & ORs in If statements

Posted: Tue Jan 27, 2009 5:25 pm
by endo
Hi,
In if statements it exits on first "false" when condititions ANDed, but it does not exit on first "true" when condiditons ORed. Is it a design feature? As I know it is different some other languages. Please look at the examples below.

Code: Select all

Procedure test()
	MessageRequester("test","test")
	ProcedureReturn #True
EndProcedure

a = 0
If a = 1 And test() ; test() won't be called, and it is good..
	MessageRequester("ok","ok")
EndIf

Code: Select all

Procedure test()
	MessageRequester("test","test")
	ProcedureReturn #True
EndProcedure

a = 1
If a = 1 Or test() ; test() will be called
	MessageRequester("ok","ok")
EndIf

Re: ANDs & ORs in If statements

Posted: Tue Jan 27, 2009 5:42 pm
by Little John
endo wrote:

Code: Select all

Procedure test()
	MessageRequester("test","test")
	ProcedureReturn #True
EndProcedure

a = 1
If a = 1 Or test() ; test() will be called
	MessageRequester("ok","ok")
EndIf
test is not called on my system (PB 4.30 x86 on Windows), so I can't reproduce your finding.
With which PureBasic version did you encounter this?

Regards, Little John

Re: ANDs & ORs in If statements

Posted: Tue Jan 27, 2009 6:00 pm
by endo
Little John wrote: test is not called on my system (PB 4.30 x86 on Windows), so I can't reproduce your finding.
With which PureBasic version did you encounter this?

Regards, Little John
its strange!? I'm using PB 4.30 x86 on Windows XP Pro.

Posted: Tue Jan 27, 2009 6:19 pm
by srod
Works fine here as well in that test() is not called. (PB 4.3, Vista 32).

Posted: Tue Jan 27, 2009 6:22 pm
by freak
endo:
I think you are mistaking the "Ok" Messagerequester() for the "test" one.
In the second example, there has to be 1 requester, since the If evaluates to true. There is only something wrong if you get 2 requesters.

Posted: Tue Jan 27, 2009 7:53 pm
by Marco2007
I would expect two requesters.
...and I get two, when doing this:

Code: Select all

Procedure test() 
   MessageRequester("test","test") 
   ProcedureReturn #True 
EndProcedure 

a = 1 
b=test()

If a = 1 Or test() ; test() will be called 
   MessageRequester("ok","ok") 
EndIf
or

Code: Select all

Procedure test() 
   MessageRequester("test","test") 
   ProcedureReturn #True 
EndProcedure 

a = 1 
b=test()

If a = 1 Or b ; test() will be called 
   MessageRequester("ok","ok") 
EndIf


and try this:

Code: Select all

Procedure test() 
   MessageRequester("test","test") 
   ProcedureReturn #True 
EndProcedure 

a = 1 
b=test()

If a = 1 Or test() ; test() will be called 
   MessageRequester("ok","ok") 
EndIf

If a = 1 Or test() ; test() will be called 
   MessageRequester("ok","ok") 
EndIf

Posted: Tue Jan 27, 2009 8:02 pm
by freak
Marco2007 wrote:I would expect two requesters.
...and I get two, when doing this:
Of course you get two. You moved the function call out of the If statement.

In the original example, the expected number of requester is:
0 for the And example, because the statement is false even without the evaluation of test()
1 for the Or example, because the statement is true even without the test() (so you get only the requester inside the If)

This is called "Short-circuit evaluation" and a lot of languages do it this way, because it is faster and it allows to write code like this:

Code: Select all

If *Pointer <> 0 And PeekL(*Pointer) <> 0
  ; something
EndIf
If the second part got evaluated always, this code would crash whenever *Pointer is 0. But since the second part only gets tested if the first part was true, this code works without problems.

Posted: Tue Jan 27, 2009 8:22 pm
by Marco2007
freak wrote:This is called "Short-circuit evaluation" and a lot of languages do it this way, because it is faster and it allows to write code like this: ....
.......
But since the second part only gets tested if the first part was true
I didn`t know that, although it makes sense!
Thank you :D

Posted: Tue Jan 27, 2009 10:20 pm
by idle
+ 1 on the didn't know.

Posted: Tue Jan 27, 2009 10:29 pm
by Marco2007
Hm?

Posted: Wed Jan 28, 2009 9:08 am
by endo
I could swear that test() function was called yesterday, but I guess Freak is right, it is not called if a=1.
Sorry for wasting your time :(

Code: Select all

Procedure test() 
   MessageRequester("test","test") 
   ProcedureReturn #True 
EndProcedure 

a = 1 
If a = 1 Or test() ; test() will *NOT* be called
   MessageRequester("ok","ok") 
EndIf

Posted: Wed Jan 28, 2009 12:23 pm
by srod
Aye the short circuit evaluation is very useful and if this was ever changed all of my programs would instantly crash! :)

Posted: Wed Jan 28, 2009 12:57 pm
by endo
srod wrote:Aye the short circuit evaluation is very useful and if this was ever changed all of my programs would instantly crash! :)
yep, most useful cases are:

Code: Select all

If TryOpenScreen(320,200) Or TryOpenScreen(640,480) Or TryOpenScreen(800,600)
 ;ok
Else
 ;error
EndIf
And;

Code: Select all

If OpenConsole() And Init() And OpenWindow()
;ok
End If
So Init() can give console output, and OpenWindow() is not called if init failed.

Posted: Wed Jan 28, 2009 7:18 pm
by Marco2007
idle wrote:+ 1 on the didn't know.
What does that mean?

Posted: Wed Jan 28, 2009 7:22 pm
by Kaeru Gaman
Marco2007 wrote:
idle wrote:+ 1 on the didn't know.
What does that mean?
that does just mean that idle didn't know that, too, just like you. :P