IIF functionality made simple

Share your advanced PureBasic knowledge/code with the community.
mesozorn
Enthusiast
Enthusiast
Posts: 171
Joined: Fri Feb 20, 2009 2:23 am

Re: IIF functionality made simple

Post by mesozorn »

Kaeru Gaman wrote:why 1- and Not, when you have the And..?
Because try this...

Code: Select all

z=(1 And (5.5>5.3))
Debug z
...and you'll see why I don't use it by itself. It works for variables but I prefer a version that works for everything imaginable, including literals. This way:

Code: Select all

z=(1-(1 And Not(5.5>5.6)))
Debug z
z=(1-(1 And Not(5.5>5.3)))
Debug z
...works for both/all contingencies.
mesozorn
Enthusiast
Enthusiast
Posts: 171
Joined: Fri Feb 20, 2009 2:23 am

Re: IIF functionality made simple

Post by mesozorn »

idle wrote:or this and is probably quicker than a not

Code: Select all

Macro IIFn(expr,y,n)
IIFEvaln((1 And(expr)),y,n)
EndMacro

Macro IIF(expr,y,n)
IIFEval((1 And(expr)),y,n)
EndMacro
LOL... that was my original, original version months ago, and its failure to properly handle literal floats like (5.5>5.3) as expressions is what led me down the whole Val(Str()) path in the first place. It's true that the above will work for the majority of situations, but not all of them, unlike the two versions we arrived at earlier today.
User avatar
idle
Always Here
Always Here
Posts: 5844
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: IIF functionality made simple

Post by idle »

it works for floats but it won't return them
mesozorn
Enthusiast
Enthusiast
Posts: 171
Joined: Fri Feb 20, 2009 2:23 am

Re: IIF functionality made simple

Post by mesozorn »

idle wrote:it works for floats but it won't return them
Er.. what do you mean exactly?
User avatar
idle
Always Here
Always Here
Posts: 5844
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: IIF functionality made simple

Post by idle »

improved the string speed but you need to pass the address of the string
just call the macro with the return types you want

edit bloddy dyslexia!

edit to NOT as (1 And 5.5 = 5.6) dosen't work

iFFI , iFFF, IFFD, IFFQ, IFFS

Code: Select all

Procedure.s IIFEvals(expr,*y,*n)
If expr
 ProcedureReturn PeekS(*y)
Else
 ProcedureReturn PeekS(*n)
EndIf
EndProcedure

Procedure IIFEvali(expr,y,n)
If expr
  ProcedureReturn y
Else
  ProcedureReturn n
EndIf
EndProcedure

Procedure.f IIFEvalf(expr,y.f,n.f)
If expr
  ProcedureReturn y
Else
  ProcedureReturn n
EndIf
EndProcedure

Procedure.d IIFEvald(expr,y.d,n.d)
If expr
  ProcedureReturn y
Else
  ProcedureReturn n
EndIf
EndProcedure

Procedure IIFEvalq(expr,y.q,n.q)
If expr
  ProcedureReturn y
Else
  ProcedureReturn n
EndIf
EndProcedure

Macro IFFI(expr,y,n)
IIFEvali((Not(expr)),n,y)
EndMacro

Macro IFFF(expr,y,n)
IIFEvalf((Not(expr)),n,y)
EndMacro

Macro IFFD(expr,y,n)
IIFEvald((Not(expr)),n,y)
EndMacro

Macro IFFQ(expr,y,n)
IIFEvalf((Not(expr)),n,y)
EndMacro

Macro IFFS(expr,y,n)
IIFEvals((Not(expr)),n,y)
EndMacro

Macro IFFfn(expr,a,b)
 If expr : a : Else : b : EndIf  
EndMacro 

Procedure p2(a.s)
  MessageRequester("test",a)
EndProcedure
  

a=5
b=4
c=2
d=3
e.f = 5.6
f.f = 5.5 

IFFfn(5>4,p2("hello"),MessageRequester("test","no"))
Debug IFFS(5.5>5.4,@"yes",@"no")
Debug IFFI(a > b,200,100) 
Debug IFFF(e > f,200.1234567,100.1234567)
Debug IFFD(5.5 = 5.6,200.123456789012345,10.123456789012345)
Debug IFFQ(a > c,$FFFFFFFF,$EEEEEEEE)


lp = 1000000
st = GetTickCount_()
For a = 1 To lp
   x$ = iFFs(5.5 > 7.5,@"200",@"100")
Next   
et1.f = (GetTickCount_() - st) / lp
st = GetTickCount_()
For a = 1 To lp
   If 5.5 > 7.5
      x$ = "200"
   Else
      x$ = "100"     
   EndIf
Next     
et2.f = (GetTickCount_() - st) / lp


MessageRequester("test", "IFFs " + StrF(et1,6) + " if " + StrF(et2,6))
Last edited by idle on Tue Nov 10, 2009 8:23 am, edited 2 times in total.
mesozorn
Enthusiast
Enthusiast
Posts: 171
Joined: Fri Feb 20, 2009 2:23 am

Re: IIF functionality made simple

Post by mesozorn »

idle wrote:improved the string speed but you need to pass the address of the string
just call the macro with the return types you want
It still doesn't handle literal floats correctly though with only (1 and expr). Uncomment and change your line to:

Code: Select all

Debug IIFD(5.5=5.6,200.123456789012345,10.123456789012345)
Debug IIFS(5.5>5.7,@"yes",@"no")
...and note that it still returns the "yes" result both times, even though 5.5 doesn't equal 5.6 in the first example, and 5.5 isn't greater than 5.7 in the second.
User avatar
idle
Always Here
Always Here
Posts: 5844
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: IIF functionality made simple

Post by idle »

ohh crap! yes you are right :lol:

changed it back to not
mesozorn
Enthusiast
Enthusiast
Posts: 171
Joined: Fri Feb 20, 2009 2:23 am

Re: IIF functionality made simple

Post by mesozorn »

idle wrote:ohh crap! yes you are right :lol:
Hehe... for those ones it seems we still can't get away from using one of the two methods discovered earlier to handle them accurately. Either just the Not by itself or the "barbarous abomination" (1-(1 And Not(expr))).

I still don't know why only the barbarous one returns correctly in all cases (straight variable value assign debug) while the Not one by itself only works in the procedure but not independently. Odd quirk.
User avatar
idle
Always Here
Always Here
Posts: 5844
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: IIF functionality made simple

Post by idle »

I don't know anymore I'm so confused. :lol:
It appears to be around a 2x speed penalty in all cases so it's a pretty good improvement.

Code: Select all

 
Procedure.s IIFEvals(expr,*y,*n)
If expr
   ProcedureReturn PeekS(*y)
Else
   ProcedureReturn PeekS(*n)
EndIf
EndProcedure

Procedure.i IIFEvali(expr,y,n)
If expr
  ProcedureReturn y
Else
  ProcedureReturn n
EndIf
EndProcedure

Procedure.f IIFEvalf(expr,y.f,n.f)
If expr
  ProcedureReturn y
Else
  ProcedureReturn n
EndIf
EndProcedure

Procedure.d IIFEvald(expr,y.d,n.d)
If expr
  ProcedureReturn y
Else
  ProcedureReturn n
EndIf
EndProcedure

Procedure.q IIFEvalq(expr,y.q,n.q)
If expr
  ProcedureReturn y
Else
  ProcedureReturn n
EndIf
EndProcedure

Macro IIFI(expr,y,n)
IIFEvali((Not(expr)),n,y)
EndMacro

Macro IIFF(expr,y,n)
IIFEvalf((Not(expr)),n,y)
EndMacro

Macro IIFD(expr,y,n)
IIFEvald((Not(expr)),n,y)
EndMacro

Macro IIFQ(expr,y,n)
IIFEvalf((Not(expr)),n,y)
EndMacro

Macro IIFS(expr,y,n)
IIFEvals((Not(expr)),n,y)
EndMacro

Macro IIFfn(expr,a,b)
If expr : a : Else : b : EndIf 
EndMacro 

;================================

Procedure p1(a.s)
   MessageRequester("P1",a)
EndProcedure
Procedure p2(a.s)
 result =  MessageRequester("P2",a,#PB_MessageRequester_YesNo)
 If result = #PB_MessageRequester_Yes
   ProcedureReturn 1 
 Else 
   ProcedureReturn 0
 EndIf      
EndProcedure

a=5
b=4
c=2
d=3
e.f = 5.6
f.f = 5.5
                            
Debug IIFS(5.4 = 5.4,@"yes",@"no") ;string return 
                  
Debug IIFI(a > b,200,100) ;Integer return  
         
Debug IIFF(e > f,200.1234567,100.1234567) ;float return 
        
Debug IIFD(5.5 = 5.6,200.123456789012345,10.123456789012345) ;Double return 
        
Debug IIFQ(a > c,$FFFFFFFFF,$EEEEEEEE) ;quad return 

;function call a regular macro with no return    
IIFfn(a>b And c>d,p1("true"),p1("false"))

; iif as a parameter in a function expecting a string calling a function with the result from the input 
p1(iifs(p2("Click Yes or Cancel"),@"You Clicked Ok",@"You Clicked Cancel"))

;iif getting the result of a function 
If CreateFile(0, "MacroTest.txt")
CloseFile(0)
Debug "Delete File : " + IIFs(DeleteFile("MacroTest.txt"),@"Yes",@"No")
EndIf

avatar
User
User
Posts: 35
Joined: Fri Apr 16, 2010 11:43 am

Re: IIF functionality made simple

Post by avatar »

This is my version of string handling in IIF

Code: Select all

Procedure.s IIFEvalss(expr,y.s,n.s)
  If expr
     ProcedureReturn y
  Else
     ProcedureReturn n
  EndIf
EndProcedure
Macro IIFSS(expr,y,n)
  IIFEvalss((Not(expr)),n,y)
EndMacro

Debug iifss(1=0,"TRUE","FALSE")
Debug iifss(1=1,"TRUE","FALSE")
Post Reply