Seite 1 von 2
Inline-If
Verfasst: 06.03.2016 14:37
von Sicro
Code: Alles auswählen
Macro Iif(Expression, TrueValue, FalseValue)
FalseValue + Bool(Expression) * (TrueValue - FalseValue)
EndMacro
Macro IifS(Expression, TrueString, FalseString, Separator = "|")
StringField(FalseString + Separator + TrueString, Bool(Expression) + 1, Separator)
EndMacro
Debug IifS(1 = 1, "Ja", "Nein")
Debug IifS(1 = 0, "Ja", "Nein")
Debug Iif(1 = 1, 11, 55)
Debug Iif(1 = 0, 11, 55)
Eine native Implementierung wäre sicherlich performanter...
Hier noch ein Speed-Test:
Code: Alles auswählen
CompilerIf #PB_Compiler_Debugger
CompilerError "Debugger ausschalten!"
CompilerEndIf
; !!!!!!!!! Purifier ebenfalls ausschalten !!!!!!!!!
Macro Iif(Expression, TrueValue, FalseValue)
FalseValue + Bool(Expression) * (TrueValue - FalseValue)
EndMacro
Macro IifS(Expression, TrueString, FalseString, Separator = "|")
StringField(FalseString + Separator + TrueString, Bool(Expression) + 1, Separator)
EndMacro
Define.s Result$
Define.i Result, Time, Time_Result_1, Time_Result_2, i
#Rounds = 100000000
Time = ElapsedMilliseconds()
For i = 1 To #Rounds
Result$ = IifS(1 = 1, "Ja", "Nein")
Result$ = IifS(1 = 0, "Ja", "Nein")
Result = Iif(1 = 1, 11, 22)
Result = Iif(1 = 0, 11, 22)
Next
Time_Result_1 = ElapsedMilliseconds() - Time
Time = ElapsedMilliseconds()
For i = 1 To #Rounds
If 1 = 1 : Result$ = "Ja" : Else : Result$ = "Nein" : EndIf
If 1 = 0 : Result$ = "Ja" : Else : Result$ = "Nein" : EndIf
If 1 = 1 : Result = 11 : Else : Result = 22 : EndIf
If 1 = 0 : Result = 11 : Else : Result = 22 : EndIf
Next
Time_Result_2 = ElapsedMilliseconds() - Time
MessageRequester("", Str(Time_Result_1) + #CRLF$ + Str(Time_Result_2))
Re: Inline-If
Verfasst: 06.03.2016 14:50
von RSBasic
Ich hoffe, dass PB das irgendwann selber kann.
Re: Inline-If
Verfasst: 06.03.2016 14:57
von mk-soft
Etwas kürzer
Code: Alles auswählen
Macro IifS(Expression, TrueString, FalseString)
Left(TrueString, Bool(Expression) * Len(TrueString)) + Left(FalseString, Bool(Not Expression) * Len(FalseString))
EndMacro
Macro Iif(Expression, TrueValue, FalseValue)
Bool(Expression) * TrueValue + Bool(Not (Expression)) * FalseValue
EndMacro
Debug IifS(1 = 1, "Ja", "Nein")
Debug IifS(1 = 0, "Ja", "Nein")
Debug Iif(1 = 1, 11, 55)
Debug Iif(1 = 0, 11, 55)
Re: Inline-If
Verfasst: 06.03.2016 21:06
von NicTheQuick
Man sollte auch den Nebeneffekt beachten, dass "Expression" zweimal ausgeführt wird. Falls Expression eine Funktion ist, wird diese dann auch zweimal ausgeführt, was oftmals nicht gewünscht ist.
Re: Inline-If
Verfasst: 06.03.2016 22:33
von Sicro
@NicTheQuick:
Da hast du recht. Ich habe meinen Code durch eine bessere Version ersetzt. Nun wird die "Expression" immer nur einmal ausgeführt.
Ein Trennzeichen wollte ich eigentlich weglassen, weshalb ich bei der ersten Code-Version auf StringField() verzichtet habe, aber nun habe ich keine andere Wahl.
Re: Inline-If
Verfasst: 07.03.2016 00:14
von STARGÅTE
Ist nicht böse gemeint, aber wie ich im englischen Forum schon schrieb, halte ich nichts von diesen Inline-If Sachen (zumindest nicht in diesem selbstgemachten Zustand).
Speziell geht es um die Problematik, dass beide Zustände (True und False) immer ausgeführt werden, was in diesem Fall z.B. zu Problemen führt:
Code: Alles auswählen
Macro Iif(Expression, TrueValue, FalseValue)
Bool(Expression) * TrueValue + Bool(Not (Expression)) * FalseValue
EndMacro
Define x.f
x.f = 2.0
Debug Iif(x<>0, 1/x, 0)
x.f = 0.0
Debug Iif(x<>0, 1/x, 0) ; sollte 0 zurückgeben
Probleme gibt es auch mit einer Prozedur, welche die Arithmetik umgeht:
Code: Alles auswählen
Procedure.f Iif_(Query, True.f, False.f)
If Query
ProcedureReturn True
Else
ProcedureReturn False
EndIf
EndProcedure
Macro Iif(Expression, TrueValue, FalseValue)
Iif_(Bool(Expression), TrueValue, FalseValue)
EndMacro
Define x.f
x.f = 2.0
Debug Iif(x<>0, 1/x, 0)
x.f = 0.0
Debug Iif(x<>0, 1/x, 0)
Hier bekommt man sofort die Fehlermeldung, dass nicht durch Null geteilt werden darf, weil eben beide Parameter ausgeführt werden.
Darum hier meine Bitte, doch bitte lieber auf eine echte Implementierung zu warten, statt "unechte" Tricks zu posten.
Re: Inline-If
Verfasst: 07.03.2016 08:42
von Nino
@Stargate:
Ich finde nicht, dass das was Du schreibst generell gegen das Verwenden von selbstgemachtem "Inline-If" spricht. Auch wenn man das normale "If" benutzt darf man nicht durch 0 dividieren. Ja, da gibt es zwar in PB die Kurzschlussauswertung, aber auch dabei muss man wissen was man macht.
@Sicro:
Danke für diese Vorschläge!
Die numerischew Version lässt sich noch etwas vereinfachen, indem man auf das "Not" verzichtet, und da du in der String-Version für das Trennzeichen eine Variable benutzt, muss es natürlich
überall als Variable auftauchen.
//edit: evtl. missverständliche Formulierung geändert
Code: Alles auswählen
Macro Iif(Expression, TrueValue, FalseValue)
FalseValue + Bool(Expression) * (TrueValue - FalseValue)
EndMacro
Macro IifS(Expression, TrueString, FalseString, Separator = "|")
StringField(FalseString + Separator + TrueString, Bool(Expression) + 1, Separator)
EndMacro
Re: Inline-If
Verfasst: 07.03.2016 09:03
von mhs
Im einem anderen Thread (
http://purebasic.fr/german/viewtopic.ph ... 0&start=10) hatte ich schon mal meine Variante gepostet. Total simpel, dafür nicht komplett Inline, weil die Result Variable mit als Paramter übergeben werden muss... dafür ohne Performanceverlust, doppelter Ausführung der Expression... ist ja schließlich nur ein simples If : Else
Code: Alles auswählen
Macro If_set(Result, Expression, TrueValue, FalseValue)
If Expression
Result = TrueValue
Else
Result = FalseValue
EndIf
EndMacro
Define a.s, b.i
If_set(a, 1 = 1, "Ja", "Nein") : Debug a
If_set(a, 1 = 0, "Ja", "Nein") : Debug a
If_set(b, 1 = 1, 11, 55) : Debug b
If_set(b, 1 = 0, 11, 55) : Debug b
Auch wenn ich gerne komplizierte Sachen mache, in dem Fall finde ich einfacher ist smarter
Eine nativle Implementation komplett inline wäre mich aber auch sehr recht...
Re: Inline-If
Verfasst: 07.03.2016 09:13
von uweb
Ich finde Stargate hat im Prinzip recht. Wenn es doch aber Spaß macht ...
Außerdem weiß man nie was raus kommt solange man es nicht probiert.
Gestern ist Ray Tomlinson gestorben.
Ich möchte nicht wissen was seine Zeitgenossen damals dachten als er die E-Mail erfand.
Wenn es möglich ist mit festen Ergebnissen zu arbeiten kann man auch ein Array oder Konstanten verwenden.
Irgendwo habe ich gelesen, dass Konstanten schneller als Variablen seien.
Wenn man die Reihenfolge der Messungen ändert, ändert sich aber auch das Ergebnis.
Code: Alles auswählen
CompilerIf #PB_Compiler_Debugger
CompilerError "Debugger ausschalten!"
CompilerEndIf
; !!!!!!!!! Purifier ebenfalls ausschalten !!!!!!!!!
Define.s Result$
Define.i Result, Time, Time_Result_1, Time_Result_2, Time_Result_3, i
#Rounds = 100000000
Dim ResultArray(1)
ResultArray(0) = 11
ResultArray(1) = 22
#T=11
#F=22
Macro Iif(Expression, TrueValue, FalseValue)
TrueValue + Bool(Not (Expression)) * (FalseValue - TrueValue)
EndMacro
Macro IifA(Expression)
ResultArray(Bool(Expression))
EndMacro
Macro IifK(Expression)
#T + Bool(Not (Expression)) * (#F - #T)
EndMacro
x.f = 0.0
MessageRequester("", Str(Iif(x<>0, 1/x, 11)) + #CRLF$ + Str(IifA(x<>0))+ #CRLF$ + Str(IifK(x<>0)))
Time = ElapsedMilliseconds()
For i = 1 To #Rounds
Result = Iif(1 = 1, 11, 22)
Result = Iif(1 = 0, 11, 22)
Next
Time_Result_1 = ElapsedMilliseconds() - Time
Time = ElapsedMilliseconds()
For i = 1 To #Rounds
Result = IifA(1 = 1)
Result = IifA(1 = 0)
Next
Time_Result_2 = ElapsedMilliseconds() - Time
Time = ElapsedMilliseconds()
For i = 1 To #Rounds
Result = IifK(1 = 1)
Result = IifK(1 = 0)
Next
Time_Result_3 = ElapsedMilliseconds() - Time
MessageRequester("", Str(Time_Result_1) + #CRLF$ + Str(Time_Result_2)+ #CRLF$ + Str(Time_Result_3))
Re: Inline-If
Verfasst: 07.03.2016 12:19
von STARGÅTE
@Nino:
>> "Auch wenn man das normale "If" benutzt darf man nicht durch 0 dividieren."
Richtig, aber beim normalen If, frage ich das ja vorher auch ab, ob x<>0 und lasse dann nur 1/x zu!
Bei deinem Inline-If wird das 1/x leider in jedem Fall ausgeführt.
@mhs:
Deine Variante ist wiederum nicht Inline, somit scheiden Zuweisungen und arithmetische Verschachtelungen aus.