Inline-If

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
Sicro
Beiträge: 955
Registriert: 11.08.2005 19:08
Kontaktdaten:

Inline-If

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

Code: Alles auswählen

10931
6439
Zuletzt geändert von Sicro am 07.03.2016 20:46, insgesamt 3-mal geändert.
Bild
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Benutzeravatar
RSBasic
Admin
Beiträge: 8022
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: Inline-If

Beitrag von RSBasic »

:allright:

Ich hoffe, dass PB das irgendwann selber kann.
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Benutzeravatar
mk-soft
Beiträge: 3695
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Inline-If

Beitrag 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)
:wink:
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Inline-If

Beitrag 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.
Bild
Benutzeravatar
Sicro
Beiträge: 955
Registriert: 11.08.2005 19:08
Kontaktdaten:

Re: Inline-If

Beitrag 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.
Bild
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 6996
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Inline-If

Beitrag 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.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Nino
Beiträge: 1300
Registriert: 13.05.2010 09:26
Wohnort: Berlin

Re: Inline-If

Beitrag 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
Zuletzt geändert von Nino am 07.03.2016 09:15, insgesamt 1-mal geändert.
Benutzeravatar
mhs
Beiträge: 224
Registriert: 11.01.2009 16:30
Wohnort: Graben
Kontaktdaten:

Re: Inline-If

Beitrag 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 :lol:

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...
Michael Hack

Michael Hack Software :: Softwareentwicklung | Webentwicklung | IT-Dienstleistungen
www.michaelhacksoftware.de :: www.mh-s.de :: www.michael-hack.de
Benutzeravatar
uweb
Beiträge: 461
Registriert: 13.07.2005 08:39

Re: Inline-If

Beitrag 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))
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 6996
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Inline-If

Beitrag 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.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Antworten