ways to write if and or parenthesis (for the same

Community Forums/General Help/ways to write if and or parenthesis (for the same

RemiD(Posted 2016) [#1]
ways to write if and or parenthesis (for the same logic)

Hello, :)

Here is a small test writing the same logic but in different ways (Blitz3d or BlitzPlus) :

All seem to work well, however i prefer the way 3 because i find it more clear.

How would you write the same logic and why write it this way ?


Dan(Posted 2016) [#2]
I would use the #2 (without () at the TRef part), simply because you save 1 comparison.
The Second reason is, if you want to change TRef to 1, you would need to do it on both sides (on case 3) and this would mean, 1 useless step.


RemiD(Posted 2016) [#3]
Personally, i find the #1 confusing...

using And can be considered like another if() isn't it ?
for example, #1 is the same as #2 yes ? no ?


Floyd(Posted 2016) [#4]
I would prefer style 2 which seems to express the idea more naturally. Style 1 is not the same logic.

You have three conditions:

TRef = 0
TList = ""
TList = "LEV"

Let's give them names A,B,C each of which can be True or False. Note True and False are just names for 1 and 0.

There are eight different configurations. We can test them all with your three versions.

If the three tests were equivalent then the only results would 000 and 111. As you can see this is not the case when A is False and C is True.

Graphics3D 640,480,0,2 
SetBuffer FrontBuffer()

For A = 0 To 1
	For B = 0 To 1
		For C = 0 To 1
		
			results$ = " ABC = " + A + B + C + "   results = "
			If A And B Or C
				results = results + "1"
			Else
				results = results + "0"
			EndIf 
			
			If A And ( B Or C )
				results = results + "1"
			Else
				results = results + "0"
			EndIf 		
			
			If ( A And B ) Or ( A And C )
				results = results + "1"
			Else
				results = results + "0"
			EndIf 

			Print results
						
		Next
	Next
Next

WaitKey



RemiD(Posted 2016) [#5]
Yes i see the difference now.
#2 and #3 are the same logic, #1 is not.
but what can be confusing is writing #1 like this :

which could be the same wanted logic than #3 or #4 but apparently is not recognized as the same...


Floyd(Posted 2016) [#6]
Another test
Graphics3D 640,480,0,2 
SetBuffer FrontBuffer()

For A = 0 To 1
	For B = 0 To 1
		For C = 0 To 1
		
			results$ = " ABC = " + A + B + C + "   results = "
			If A And B Or A And C
				results = results + "1"
			Else
				results = results + "0"
			EndIf 
			
			If ( ( A And B ) Or A ) And C 
				results = results + "1"
			Else
				results = results + "0"
			EndIf 		
			
			If ( A And B ) Or ( A And C )
				results = results + "1"
			Else
				results = results + "0"
			EndIf 

			Print results
						
		Next
	Next
Next

WaitKey

The first two are equivalent but the third is not. It differs in a single case, ABC = 110.

The problem is that And has the same precedence as Or. I would expect it to be higher since And,Or are analogous to Multiplication,Addition.
But Blitz3D goes its own way.

Unfortunately the Blitz Basic Language Reference is not online. You can find it in IDE. The preference table is on the Expressions page.


RemiD(Posted 2016) [#7]

The problem is that And has the same precedence as Or. I would expect it to be higher since And,Or are analogous to Multiplication,Addition.
But Blitz3D goes its own way.


Yes it is probably better to separate every different logical test with parentheses, just to be sure...


Cocopino(Posted 2016) [#8]
I always force my precendence (regardless of language) like:
If not Tref
	If TList = "" Or TList = "LEV" doStuff()
Endif

More readable to me in this case as well, since all comparisons need Tref to be 0.


Flanker512(Posted 2016) [#9]
I agree with Cocopino, and this way is useful because you can add an ElsIf statement for every step you check.

Also, I remember a code recently in the code archives (check a point in a polygon shape), it worked fine but quite slow, someone rewrote the If ElseIf statements a more clever way and performances improved by almost a factor of 2.


RemiD(Posted 2016) [#10]
the correct way to write this is to consider the OR like a separate if()
like this :
Graphics3D(640,480,32,2)

TRef% = 0 ; 0
TList$ = "" ; "" or "LEV"

If( TRef = 0 And TList = "" ) Or ( TRef = 0 And TList = "LEV" )
 DebugLog("here")
EndIf 

WaitKey()

End()



TomToad(Posted 2016) [#11]
the correct way to write this is to consider the OR like a separate if()

The correct way depends on what you are trying to achieve and your own style (or the style required by the company you are working for).

For performance, it is better to write it like this
If TRef = 0 And (TList = "" Or TList = "LEV")

Your version will require four comparisons while my version will require three. With BlitzMax, the difference is greater as comparisons stop as soon as the program can determine the rest. For example, if TRef = 1, then TList will not need to be evaluated.

The BlitzMax code below will show how the checks are done by calling a function for each check. You can clearly see that My version out performs yours in every single combination


The resulting printout



Edit to add: If using Blitz Basic (Blitz+ or Blitz3D), Cocopino's version works best as it will save you 2 comparisons when TRef <> 0.


col(Posted 2016) [#12]
A little tip some may not know: If the first expression of an 'And' comparison is false then the 2nd expression of it isn't even computed and the 'And' comparison doesn't take place.

The real number of comparisons taking place ( ignoring the inners of the string compares ) are
If( TRef = 0 And TList = "" ) Or ( TRef = 0 And TList = "LEV" )

1. (TRef = 0
2. And
3. List = "")
4. Or
5. (TRef = 0
6. And
7. List = "LEV")

When TRef = 0 then all comparions are done - 1, 2, 3, 4, 5, 6, 7
When TRef <> 0 then 3 comparisons take place. 1, 4, 5.


If TRef = 0 And (List = "" or List = "LEV")

1. TRef = 0
2. And
3. (List = ""
4. Or
5. List = "LEV")

When TRef = 0 then 1, 2, 3, 4, 5 are done
When TRef <> 0 then 1 is done


If not Tref
	If TList = "" Or TList = "LEV" doStuff()
Endif

1. not Tref
2. TList = ""
3. Or
4. TList = "LEV"

When Tref = 0 then 1, 2, 3, 4 are done
When Tref <> 0 then 1 is done


RemiD(Posted 2016) [#13]
not sure if these rules are the same for all languages, but in doubt, if you have an error in your code and you don't know the cause, you may want to try to debug your if() which contains AND/OR because sometimes what you have written seems logical but the language may interpret it differently (depending on where you put the parenthesis)


col(Posted 2016) [#14]
I think you'll find that the 'And' rule applies to pretty most programming languages, yes. It's been a standard form of optimisation from day one of compiler birth.
The concept is that if the first expression is false there's no point in checking the second expression on account that the whole 'And' expression would be false already.


TomToad(Posted 2016) [#15]
Blitz3D does not short-circuit the evaluation, so all comparisons are evaluated. BlitzMAX will short-circuit once it can be determined if the If statement will pass or fail.

So in BlitzMax, you can check if a handle exists before doing something with it like so
If Image And Image.Width > Image.Height then ...
If Image = Null, then BlitzMax will never attempt to read the Width and Height fields. But in Blitz3D
If Image And Image\Width > Image\Height Then...
Will result in an error if Image doesn't point to a valid handle as all terms will be evaluated. In that case, you would need Col's third version to keep the checks safe.
If Image
If Image\Width > Image\Height Then...
EndIf



col(Posted 2016) [#16]
Blitz3D does not short-circuit the evaluation

Ahh cool, good to know! A bad assumption on my part.

I was under the impression that all languages did the 'And' optimisation. Of the BRL family of languages I only use Blitzmax and BlitzmaxNG. All other languages that I use don't evaluate the second expression if the first one fails and, as you say, Blitzmax* doesn't do it either.

you would need Col's third version to keep the checks safe

*passes credit to Cocopino*


_PJ_(Posted 2016) [#17]
I never combine And and Or simply because it is so easily to introduce errors due to misinterpreting the precedence or incorrect brackets.

Actually I avoid using Then unless it's a single line (single statement even, I avoid : too)
And furthermore, I can't abide ElseIf as well.

Any situation where there may be (perceived or otehrwsie) potential ambiguity I like to eradicate it entirely.

Therefore I try to opt for a long-winded and verbose approach.

If (Condition1)
	If (Condition2)
		If (Condition3)
			;123
		Else
			;1,2
		End If
	Else
		If (Condition3)
			;1,3
		Else
			;1
		End If
	End If
Else
	If (Condition2)
		If (Condition3)
			;2,3
		Else
			;2
		End If
	Else
		If (Condition3)
			;3
		Else
			; 0
		End If
	End If
End If


The intention of course should always reflect the coder's preference and requirements. For me I want to be able to see the clauses expanded and specific so I can narrow down quickly and easily either to make changes or track down bugs.
Whilst there may be slight optimisation benefits I think these are possibly far less critical so long as the overall approach is methodical.