PureBoard
http://forums.purebasic.com/german/

Inline-If
http://forums.purebasic.com/german/viewtopic.php?f=8&t=29487
Seite 1 von 2

Autor:  Sicro [ 06.03.2016 14:37 ]
Betreff des Beitrags:  Inline-If

Code:
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:
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))
Code:
10931
6439

Autor:  RSBasic [ 06.03.2016 14:50 ]
Betreff des Beitrags:  Re: Inline-If

:allright:

Ich hoffe, dass PB das irgendwann selber kann.

Autor:  mk-soft [ 06.03.2016 14:57 ]
Betreff des Beitrags:  Re: Inline-If

Etwas kürzer
Code:
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)

:wink:

Autor:  NicTheQuick [ 06.03.2016 21:06 ]
Betreff des Beitrags:  Re: Inline-If

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.

Autor:  Sicro [ 06.03.2016 22:33 ]
Betreff des Beitrags:  Re: Inline-If

@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.

Autor:  STARGÅTE [ 07.03.2016 00:14 ]
Betreff des Beitrags:  Re: Inline-If

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:
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:
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.

Autor:  Nino [ 07.03.2016 08:42 ]
Betreff des Beitrags:  Re: Inline-If

@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:
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

Autor:  mhs [ 07.03.2016 09:03 ]
Betreff des Beitrags:  Re: Inline-If

Im einem anderen Thread (http://purebasic.fr/german/viewtopic.php?f=8&t=4840&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 :lol:

Code:
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...

Autor:  uweb [ 07.03.2016 09:13 ]
Betreff des Beitrags:  Re: Inline-If

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:
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))

Autor:  STARGÅTE [ 07.03.2016 12:19 ]
Betreff des Beitrags:  Re: Inline-If

@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.

Seite 1 von 2 Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/