Wenn dies dein erster Besuch hier ist, lies bitte zuerst die Hilfe - Häufig gestellte Fragen durch. Du musst dich vermutlich registrieren, bevor du Beiträge verfassen kannst. Klicke oben auf 'Registrieren', um den Registrierungsprozess zu starten. Du kannst auch jetzt schon Beiträge lesen. Suche dir einfach das Forum aus, das dich am meisten interessiert.
Falsch verstanden: Eval "triggert", gibt das pro Zyklus an "AND" weiter.
Dieses ist nun zwar "angetriggert" ändert aber am Ergebnis nichts, solange der Wert sich nicht ändert. Quasi so als ob hier ständig ein Telegramm mit dem Inhalt "Wohnen" eintrifft.
Da bei AND kein eval steht, wirkt das Validierungsschema.
Anders wäre das nun bei
if eval(sun()==DUNKEL and Wohnen) then ....
Ich hoffe, das ist damit klarer.
Nein, ganz und gar nicht! Eval() soll bei wahr triggern, tut es ja auch, nur nicht, wenn ein AND dran steht????
Eval( Wohnen ) entspricht ja wohl Eval( Wohnen == EIN ), oder?
Das Validierungsschema - so es zur Anwendung kommt - triggert die Ausführung des abhängigen Codes nur, wenn sich etwas an seinem Argument geändert hat. Das passt zum ereignisorientierten Verhalten von KNX.
Das if wird in diesem Fall durch eine Änderung des Resultates der and-Funktion getriggert. Das and wiederum von der Vergleichsfunktion und der Variablen bzw. der eval-Funktion. Die Variable wird getriggert, wenn sie sich vom Wert her ändert, die Vergleichsfunktion, wenn sich eines ihrer Argumente ändert.
Nein, ganz und gar nicht! Eval() soll bei wahr triggern, tut es ja auch, nur nicht, wenn ein AND dran steht????
Eval( Wohnen ) entspricht ja wohl Eval( Wohnen == EIN ), oder?
Nein, die eval-Funktion soll in jedem Zyklus triggern, und dabei das Ergebnis der vollständigen*) Auswertung ihres Arguments weitergeben. Im vorliegenden Fall an das and. Solange das aber beim and nicht das Resultat verglichen mit den vorherigen Auswertungen ändert, gibt das and die Triggerung nicht an das if weiter. Somit ist es im vorligenden Fall egal, ob ich die Variable mit oder ohne eval() verwende. Warum geht das so sehr zu Lasten der Performance? Nun, ich schätze mal, ohne eval wird der ganze code nur angefasst, wenn sich sun() oder Wohnen ändern - DUNKEL ist ja eh konstannt. Mit eval wird immerhin in jedem Zyklus das and ausgeführt, obwohl das Resultat sich gar nicht ändern kann und das if demzufolge auch nicht getriggert werden wird.
Frage: Wird in dem Fall der Vergleich auch noch erneut ausgewertet?
Ich hoffe, das habe ich jetzt richtig verstanden...
Das Argument mit der Performance ist schwer greifbar, so lange es keine Tools für eine Messung gibt, oder?
Schwer greifbar ja, aber es ist nachvollziehbar, das es mehr Rechenzeit kostet, wenn ein kompletter Ausdruck immer wieder ausgewertet wird, statt nur dann, wenn wenigstens eines seiner Argumente sich geändert hat. Was für mich nicht greifbar ist, ist die Antwort auf die Frage, ob die Überprüfung ob etwas sich verändert hat am Ende nicht mehr Rechenzeit benötigt, als wenn man die Ausdrücke einfach stur ausgewertet hätte. Das hängt von vielen Umständen ab, vor allem auch von der Implementierung - und die kennen wir nicht genau.
*) Vollständig bedeutet, das auch alle enthaltenen Unterausdrücke ihrerseits neu ausgewertet werden, also das innerhalb von eval() das VS genauso wenig zur Anwendung kommt, wie im then oder else-Zweig. Ist das tatsächlich so?
BTW:
Triggert eine Variable von ihr abhängige Ausdrücke nur, wenn sie sich vom Wert geändert hat oder bei jeder Zuweisung?
Triggert eine GA von ihr abhängige Ausdrücke nur, wenn sie sich vom Wert geändert hat oder bei jeder Zuweisung?
Werden GAs und Variablen gleich behandelt oder nicht?
Ist bei [highlight epc]if (a>b) [/highlight]das > das Argument von if welches entscheiden kann, ob es if triggert oder gibt > bei jeder Änderung von a oder b das Ergebnis an if weiter und if entscheidet, ob es sich getriggert fühlt?
Das Validierungsschema - so es zur Anwendung kommt - triggert die Ausführung des abhängigen Codes nur, wenn sich etwas an seinem Argument geändert hat. Das passt zum ereignisorientierten Verhalten von KNX.
Puh, das klingt einleuchtend, nur hat das Validierungsschema keinen Bezug zum Bus, sondern überwacht Änderungen intern gespeicherter Zustände.
Was das Validierungsschema evtl. abbildet ist eine änderungsgetriebene Verarbeitung von Events, was auch keine spezielle Eigenschaft des KNX-Bus ist, sondern in 99,999% aller Software benötigt wird, die z.B. ein Human-Machine-Interface besitzt (HMI).
Beispiel hierfür:
[highlight=epc]
if GA then ... endif
[/highlight]
Der then-Zweig wird nur ausgeführt, wenn GA sich ändert und EIN wird. Alle Events mit Inhalt AUS bzw. alle folgenden Events mit EIN werden verworfen.
Auch wenn zusätzliche Sprachelemente die Behandlung aller Events möglicht machen, stellen diese nur einen weiteren Trigger zur Verfügung.
Beispiel:
[highlight=epc]
if event(GA) and (GA == EIN) then ... endif
[/highlight]
Hier erzeugt der event() einen trigger und somit wird der Wert der GA wieder geprüft und folglich auch beim Eintreffen eines erneuten EIN der then-Zweig ausgeführt. (Man könnte auch sagen, dass der Interne Zustand des Flags "neues Telegramm empfangen" zur GA durch das event() verfügbar wird).
Leider ist dies mit Variablen nicht möglich, denn die entsprechenden Sprachelemente wurden schlicht und einfach vergessen und Michael versteht auch den Bedarf nicht.
Beispiel:
[highlight=epc]
a=0
if systemstart() then a=1 endif
if (a<10) then a=a+1; ... endif
[/highlight]
Hier ist zwar a<10, der Vergleich ändert sich aber nicht mehr.
Event() funktioniert hier aber nicht, daher eval().
[highlight=epc]
a=0
if eval(a<10) then a=a+1; ... endif
[/highlight]
Und tatsächlich, eval() erzeugt Trigger, solange a<10. Warum Michael das bei GAs völlig problemlos implementieren kann und bei diesem Vergleich die Performance enorm leidet muss ich aber nicht verstehen.
Das if wird in diesem Fall durch eine Änderung des Resultates der and-Funktion getriggert. Das and wiederum von der Vergleichsfunktion und der Variablen bzw. der eval-Funktion. Die Variable wird getriggert, wenn sie sich vom Wert her ändert, die Vergleichsfunktion, wenn sich eines ihrer Argumente ändert.
Und wie passt das dann zu obigen Beispiel von eval()? Macht da das AND jetzt den Unterschied, bei event() aber nicht?
Nein, die eval-Funktion soll in jedem Zyklus triggern, und dabei das Ergebnis der vollständigen*) Auswertung ihres Arguments weitergeben. Im vorliegenden Fall an das and. Solange das aber beim and nicht das Resultat verglichen mit den vorherigen Auswertungen ändert, gibt das and die Triggerung nicht an das if weiter. Somit ist es im vorligenden Fall egal, ob ich die Variable mit oder ohne eval() verwende.
Und das ist nicht das geforderte Verhalten von eval(). Eval() soll den Ausdruck auswerten und dann triggern, wenn das Ergebnis EIN ist, auch wenn sich der Zustand nicht ändert. Die Implementierung wäre also falsch. Kann ich nicht glauben -> werde das aber bei Gelegenheit testen!
Eval(a<10) "triggert" immer, auch wenn das Ergebniss "AUS" = logisch 0 ist.
Das bedeutet, das in folgendem Beispiel weder Then noch Else ausgeführt werden, wenn im Zyklus n+1 das Ergebniss des Vergleiches dasselbe ist wie im Zyklus zuvor (Zyklus n):
Code:
if a<10 then bla else hot endif
Hier wird jedoch in jedem Fall immer entweder Then oder Else ausgeführt:
Puh, das klingt einleuchtend, nur hat das Validierungsschema keinen Bezug zum Bus
Ich bin da nicht Deiner Meinung.
Leider ist dies mit Variablen nicht möglich, denn die entsprechenden Sprachelemente wurden schlicht und einfach vergessen und Michael versteht auch den Bedarf nicht.
Das ist mir dann doch mal wieder etwas zu "plakativ".
Hintergrund: Event auf Variablen ist nur im eibparser gesperrt, weil wir in Betaphase damit zuviele Probleme hatten.
Damit solls genug sein von meiner Seite bzgl. der Thematik, ob es eine Frage der Dummheit oder Vergesslichkeit ist.
Würde ich eher 'Nein' sagen.
Das bedeutet
[highlight=epc]
if eval(a<10) then bla endif
if !eval(a<10) then hot endif[/highlight]
Nein, !eval() ist die Verknüpfung aus not(eval()) und bei not() wirkt das Validierungsschema. Daher:
[highlight=epc]
if eval(a<10) then xxx endif
if eval(!(a<10)) then yyy endif
[/highlight]
wäre das was Du willst.
Was das Validierungsschema evtl. abbildet ist eine änderungsgetriebene Verarbeitung von Events, was auch keine spezielle Eigenschaft des KNX-Bus ist, sondern in 99,999% aller Software benötigt wird, die z.B. ein Human-Machine-Interface besitzt (HMI).
Ja, nur das es dort nicht als spezielles Verhalten bei der Auswertung von Ausdrücken "versteckt" wird, sondern "programmierergewohnt" über Callbacks oder ähnliche Mechanismen sichtbar und vom Programmierer voll kontrollierbar implementiert ist.
Es bringt aber nichts, jetzt hier darüber zu diskutieren, ob es besser gewesen wäre, dies auch beim EPC so zu machen.
Beispiel hierfür:
[highlight=epc]
if GA then ... endif
[/highlight]
Der then-Zweig wird nur ausgeführt, wenn GA sich ändert und EIN wird. Alle Events mit Inhalt AUS bzw. alle folgenden Events mit EIN werden verworfen.
Was ich jetzt nicht gefunden habe ist eine Einsschränkung von if auf 1-Bit-Werte, wie interpretiert if z.B. u08 oder u16? So wie C, alles ungleich 0 ist wahr? In den Beispielen wird das meist hinter einem einen 1-Bit-Wert liefernden Vergleich versteckt, oder es wird einfach ein 1-Bit-Wert verwendet...
Und das ist nicht das geforderte Verhalten von eval(). Eval() soll den Ausdruck auswerten und dann triggern, wenn das Ergebnis EIN ist, auch wenn sich der Zustand nicht ändert. Die Implementierung wäre also falsch. Kann ich nicht glauben -> werde das aber bei Gelegenheit testen!
Was war den gefordert? Ich kenne auch andere Sprachen, in denen es ein eval() gibt, und in all diesen bedeutet es: arbeite den Ausdruck unbedingt ab und liefere das Ergebnis zurück, egal wie es lautet. Nicht weniger, aber auch nicht mehr. Und Funktionen sollen beim EPC doch "nach oben "triggern, sobald sie ihren Wert ändern. Bei eval würde ich zusätzlich erwarten, das es immer triggert, unabhängig von einer Änderung des Rückgabewertes. Also nicht nur bei "EIN". Es soll unbedingt trigger, sonst würde es mich wieder verwirren. Für Entscheidungen gibt es if.
Und warum wird dann nicht die Ursache angegangen, sondern das Symptom gefixt?
Weil das schneller geht. Erst einmal soll die "Gefahr gebannt" werden, dann kann man sich ja in Ruhe mit der Suche nach der Ursache und möglichen Lösungen beschäftigen - falls man das denn überhaupt will...
Ja, das stimmt.
(Vielleicht auch eine Möglichkeit für den Coding Wettbewerb: Das Valdiierungsschema schön erklären)...
Oh ja, eine vollständige und eindeutige Erklärung/Beschreibung des VS fehlt mir wirklich noch. Dabei würde dann auch auffallen, wo ggf. noch Lücken bei der vollständigen Kontrolle der Validierung sind.
Aber eher hätte mir da gewünscht: Schön implementiert.
Das Grundproblem fast aller hier ist wohl, das man es einem Ausdruck nicht ansehen kann, ob er dem Validierungsschema unterliegt oder nicht. Es gibt keinen Operator, kein Symbol, keine Funktion, kein Schlüsselwort dafür. Einzig die Position im Code entscheidet darüber, das ist bislang wohl einzigartig. Leider auch sehr fehlerträchtig, eben weil dadurch eine ziemliche Verunsicherung entstanden ist, wann es denn im eigenen Code zur Anwendung kommt und wie es sich dann genau verhält.
Nur so als Idee:
Könnte man das Syntaxhighlighting so erweitern, das es den Code entsprechend markiert, z.B. dem VS unterliegende Codeteile andersfarbig hinterlegt?
Nein, !eval() ist die Verknüpfung aus not(eval()) und bei not() wirkt das Validierungsschema.
Und du willst tatsächlich sagen, dass if eval() then .. immer triggert, wenn der Ausdruck 'wahr' wird, if !eval() then .. aber nicht bei 'falsch', und trotzdem eval() immer entweder then oder else triggert?
Könntest du deine Postings noch einmal lesen und den Widerspruch auflösen?
Was ich jetzt nicht gefunden habe ist eine Einsschränkung von if auf 1-Bit-Werte, wie interpretiert if z.B. u08 oder u16? So wie C, alles ungleich 0 ist wahr? In den Beispielen wird das meist hinter einem einen 1-Bit-Wert liefernden Vergleich versteckt, oder es wird einfach ein 1-Bit-Wert verwendet...
Stimmt, war dahingehend schon ungenau, wobei ich bei anderen Wertebereichen immer entsprechend abfragen würde, sorry.
Was war den gefordert? Ich kenne auch andere Sprachen, in denen es ein eval() gibt, und in all diesen bedeutet es: arbeite den Ausdruck unbedingt ab und liefere das Ergebnis zurück, egal wie es lautet. Nicht weniger, aber auch nicht mehr. Und Funktionen sollen beim EPC doch "nach oben "triggern, sobald sie ihren Wert ändern. Bei eval würde ich zusätzlich erwarten, das es immer triggert, unabhängig von einer Änderung des Rückgabewertes. Also nicht nur bei "EIN". Es soll unbedingt trigger, sonst würde es mich wieder verwirren. Für Entscheidungen gibt es if.
Stimmt, triggern ist relativ
Meine Anforderung war: der Ausdruck wird immer ausgewertet und entsprechend das if getriggert (wobei es dem Compiler/Interpreter/Michael überlassen war, ob er den Ausdruck nur neu berechnet, wenn sich eine Variable auch wirklich ändert). Die Aufgabe war eine Funktion, deren Ausdruck immer zu einer neuen Bewertung durch das if führt und nicht nur bei einer Änderung (und natürlich selbstredend auch nicht durch ein not() oder and() ausgebremst wird).
Die Aufgabe war nicht, das Validierungsschema für diese Funktion außer Kraft zu setzen, sondern ständig einen Trigger für das if darzustellen. Damals war übrigens noch nicht klar, dass dies innerhalb des then bereits gilt.
Die Erklärung aus den Internas zum Validierungsschema kennend hätte ich wohl etwas in die Richtung: 'eval() ist eine Funktion die sich in jedem Zyklus automatisch invalidiert', was automatisch zur invalidierung des gesamten Ausdrucken des if führt, geschrieben.
Entsprechende Beispiele waren angeführt.
Nur so als Idee:
Könnte man das Syntaxhighlighting so erweitern, das es den Code entsprechend markiert, z.B. dem VS unterliegende Codeteile andersfarbig hinterlegt?
Naja, ist nicht so mein Ding, wäre aber bestimmt hilfreich.
Und du willst tatsächlich sagen, dass if eval() then .. immer triggert, wenn der Ausdruck 'wahr' wird, if !eval() then .. aber nicht bei 'falsch', und trotzdem eval() immer entweder then oder else triggert?
Könntest du deine Postings noch einmal lesen und den Widerspruch auflösen?
Kein Widerspruch:
if ! eval() then ... ist prinzipiell gleich aufgebaut wie das Beispiel von Micha:
if (a<10) and eval(wohnen) then ...
Im Fall 2 ist das vielleicht etwas leichter zu verstehen.
Ich probiers mal zu beschreiben und fange mit Fall 3 an:
Annahme: a= 5 und Wohnen = EIN, Zyklus N wird durchlaufen
Nachfolgend die Beschreibung was im Zyklus N+1 passieren würde.
Fall 3:
Code:
if (a<10) and wohnen then bla else hot endif
3.A) a hat sich nicht geändert, wohnen hat sich nicht geändert
=> (a<10) hat sich nicht geändert => der ganze ausdruck hat sich nicht geändert => es wird WEDER then NOCH else ausgeführt!
3.B) a wird 20, wohnen hat sich nicht geändert
=> a<10 wird falsch, hat sich also auch geändert => der ganze Ausdruck hat sich geändert und ist FALSCH => else wird einmalig ausgeführt
3.C) a wird 7, wohnen bleibt EIN
=> (a<10) hat sich nicht geändert => der ganze ausdruck hat sich nicht geändert => es wird WEDER then NOCH else ausgeführt!
Fall 2:
Code:
if (a<10) and eval(wohnen) then bla else hot endif
2.A) a wird 7, wohnen hat sich nicht geändert
=> a hat sich geändert, aber a<10 hat sich nicht geändert;
eval(wohnen) liefert das gleiche Ergebniss wie wohnen =>
der ganze Ausdruck hat sich nicht geändert => es wird WEDER then NOCH else ausgeführt!
2.B) a wird 7, wohnen wird AUS
=> a hat sich geändert, aber a<10 hat sich nicht geändert;
eval(wohnen) liefert das gleiche Ergebniss wie wohnen =>
der ganze Ausdruck hat sich geändert => es wird einmalig else ausgeführt!
Fall 1:
Code:
if ! eval(wohnen) then bla else hot endif
1.A) wohnen hat sich nicht geändert, eval(wohnen) liefert also auch EIN
=> ! eval(EIN) = ! EIN => unverändert => es wird WEDER then NOCH else ausgeführt!
1.B) wohnen ändert sich zu AUS
=> eval(wohnen) ändert sich auch zu AUS => der gesamte Ausdruck hat sich geändert => else wird einmalig ausgeführt
Jetzt wirds interessant (ich füg mal extra Klammern um ! Wohnen ein, um das zu verdeutlichen):
Fall 0:
Code:
if eval( (! wohnen) ) then bla else hot endif
0.A) wohnen hat sich nicht verändert und bleibt EIN
=> ! Wohnen liefert AUS, hat sich also auch nicht verändert
=> eval ( (! Wohnen) ) "bestimmt" jetzt, dass der Ausdruck neu berechnet wurde (obwohl sich das Ergebniss an sich nicht geändert hat), damit wertet das if dieses Ergebniss aus, als ob es ein geändertes Ergebniss wäre. => Der else wird ausgeführt.
=> im nächsten Zyklus passiert das gleiche und Else wird wieder ausgeführt.
0.B) Wohnen ändert sich zu AUS
=> wie unter 0.A) wird der Ausdruck ausgewertet, das durch eval als "neu berechnet" gekennzeichnete Ergebnis lautet EIN (gesamter Ausdruck) und der Then wird ausgeführt.
=> Anschliessend wird in jedem Zyklus Then ausgeführt.
Wir verarbeiten personenbezogene Daten über die Nutzer unserer Website mithilfe von Cookies und anderen Technologien, um unsere Dienste bereitzustellen. Weitere Informationen findest Du in unserer Datenschutzerklärung.
Indem Du unten auf "ICH stimme zu" klickst, stimmst Du unserer Datenschutzerklärung und unseren persönlichen Datenverarbeitungs- und Cookie-Praktiken zu, wie darin beschrieben. Du erkennst außerdem an, dass dieses Forum möglicherweise außerhalb Deines Landes gehostet wird und bist damit einverstanden, dass Deine Daten in dem Land, in dem dieses Forum gehostet wird, gesammelt, gespeichert und verarbeitet werden.
Kommentar