Warum dieser Unterschied?

Stelle Fragen zur Programmierung mit Autohotkey

Moderator: jNizM

Rohwedder
Posts: 2347
Joined: 04 Jun 2014, 08:33
Location: Germany

Warum dieser Unterschied?

07 Oct 2019, 05:03

Hallo,
beide Hotkeys haben anscheinend denselben Code.
Aber:
G-Taste gedrückt gehalten zeigt gerade Zahlen.
U-Taste gedrückt gehalten zeigt ungerade Zahlen.

Code: Select all

Z = 0
g::
IF Mod(Z++,2)
	ToolTip,% Z
Return
u::IF Mod(Z++,2)
	ToolTip,% Z
Return
gregster
Posts: 3389
Joined: 30 Sep 2013, 06:48

Re: Warum dieser Unterschied?

07 Oct 2019, 11:31

Looks buggy tricky. Dass u hier überhaupt irgendwas macht, wundert mich.

Ein einzeiliger Hotkey dürfte eigentlich gar keine nächste Zeile ausführen, imho, wegen des impliziten Returns, sondern bei if idealerweise eine Fehlermeldung ausgeben (oder meinetwegen als Ausnahme die nächste Zeile ausführen, wenn der if-check true ergibt, aber dafür seh ich derzeit keine Anhaltspunkte in den Doks)

in den folgenden Fällen scheint es jeweils so zu sein, dass wenn der if-check true ergibt, eben nichts passiert.
Aber wenn der if-check false ergibt, wird komischerweise die folgende Zeile ausgeführt. Entweder wird in diesen Fällen das Ergebnis grundlos logisch falsifiziert oder die nächste Zeile wird als irrtümlich else-Zweig gesehen. Edit: Nee, ist wohl doch anders: Im Falle von true kommt hier immer das implizite Return zum Zuge. Siehe meinen nächsten Beitrag weiter unten...

Auf jeden Fall nicht erwartungsgemäß - sieht für mich derzeit wie ein Bug aus. Edit: Zumindest tricky.

Code: Select all

c = 0
q::if c++
	msgbox % c	; zeigt 1 im ersten Durchlauf (wenn c noch 0 = false war), dann nix mehr
Return

1::if (3 > 5)
	msgbox		; zeigt msgbox, obwohl false
return	
2::if !(3 > 5)	
	msgbox		; zeigt keine msgbox, obwohl true
return
3::if false
	msgbox		; zeigt msgbox, obwohl false
return
4::if true	
	msgbox		; zeigt keine msgbox, obwohl true
return
5::if !true
	msgbox		; ; zeigt msgbox, obwohl false
return
gregster
Posts: 3389
Joined: 30 Sep 2013, 06:48

Re: Warum dieser Unterschied?

07 Oct 2019, 11:41

Ich nehme an, der if-check reklamiert die implizite Return-Zeile für sich - als nächste Zeile, in seinem true-Zweig.

Wenn if true , dann wird die Hotkey-Routine beendet (wegen des impliziten Returns in der nächsten Zeile wird immer unverzüglich returniert); aber das führt für den Nutzer - unter Umständen - zu etwas unerwarteten Ergebnissen. ;)

Wenn der if-check aber false ergibt, dann wird dieses implizite Return nicht ausgeführt (es wird schließlich schon für den obligatorischen true-Zweig beansprucht) und es wird dann bis zum nächsten Return jeglicher Code ausgeführt:

Code: Select all

5::if !true		; hier folgt ein implizites Return
	msgbox		; zeigt msgbox, obwohl false
msgbox 2
return
Es passiert also folgendes (äquivalent zu oben)

Code: Select all

5::
if !true
	return		; oben ist dieses return implizit
msgbox		
msgbox 2
return
Macht schon Sinn, aber ob das syntaktisch ideal für den Nutzer ist, ist ne andere Frage :)

Code: Select all

4::if true	
	msgbox		; zeigt keine msgbox, obwohl true
return
; ist äquivalent zu: 
4::
if true	
	return	; ist oben implizit
msgbox		; Code ist unerreichbar
return
gregster
Posts: 3389
Joined: 30 Sep 2013, 06:48

Re: Warum dieser Unterschied?

07 Oct 2019, 12:00

Ich muss aber sagen, ich wär nie auf die Idee gekommen, einen If-Baum als Einzeiler-Hotkey anlegen zu wollen (außer als ternary).

Das sagt natürlich nichts über die allgemeine Nutzererwartung bzw. das allgemeine oder individuelle Nutzerverhalten, aber: "However, if a hotkey needs to execute only a single line, that line can be listed to the right of the double-colon."

Das passt für mich so gar nicht zur Struktur eines If-Statements: Ein if-Baum mit seiner nächsten Zeile ist ja keine continuation section, die formal nur aus einer einzigen Zeile besteht, sondern eine Struktur, die immer aus zwei Zeilen besteht (oder einem { }-Block an Stelle der zweiten Zeile). Daher hätte ich die Hotkey-Einzeilersyntax und If grundsätzlich als unverträglich angesehen und noch nicht mal den Versuch unternommen, die beiden zu kombinieren. :) (Naja, so richtig harmonieren tun sie ja tatsächlich nicht.)

Aber wir sehen, wenn man die implizite Return-Zeile (in Gedanken) als nächste Zeile ergänzt, so wie es der AHK-Interpreter tatsächlich macht - dann passt die Logik wieder... auch, wenn man zunächst stutzt und das Konstrukt in Verbindung mit If nur begrenzten Nutzwert hat.

Ich glaube wir haben uns hier schon mal über das implizite Return bei Hotkey-Einzeilern unterhalten :think:

Edited
Rohwedder
Posts: 2347
Joined: 04 Jun 2014, 08:33
Location: Germany

Re: Warum dieser Unterschied?

08 Oct 2019, 09:59

Stimme dem Ergebnis deiner ausführlichen Analyse voll und ganz zu.
Die impliziten Returns (vor und nach: if !true) kann man übrigens hier in der Fehlermeldung, aufgrund des isolierten Switch, sehen:

Code: Select all

5::if !true		; hier folgt ein implizites Return
	msgbox		; zeigt msgbox, obwohl false
msgbox 2
return
Switch
Execute-Hotstrings (X-Option) haben das gleich Verhalten.
Leider wird der Nutzwert dieses Konstrukt durch die Verschlechterung der Kodelesbarkeit mehr als aufgezehrt.

Stimmt, wir hatten uns bereits über das implizite Return bei Hotkey-Einzeilern unterhalten.
Ging mir wie dir!
Manches muß man mehrmals begreifen bis man es kapiert.
just me
Posts: 6557
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Warum dieser Unterschied?

09 Oct 2019, 03:56

Auch ich teile @gregster's Einschätzung. Ich denke aber, dass das nicht 'tricky' sondern 'buggy' ist.

Unter 'normalen' Umständen wird ein weiterer Befehl auf der Zeile der If-Aweisung nur für das 'traditionelle' If unterstützt. Für den Ausdruck IF Mod(Z++,2) sollte es also schon mal nicht funktionieren. Ich halte es generell für sinnlos, If-Anweisungen als 'einzeilige' Hotkeys überhaupt zuzulassen.
gregster
Posts: 3389
Joined: 30 Sep 2013, 06:48

Re: Warum dieser Unterschied?

09 Oct 2019, 06:29

just me, ich hab das ein klein wenig anders verstanden.

Ich glaube nicht, dass das implizite Return tatsächlich eines ist, das auf der gleichen Zeile (wie das If bzw. der Zeile des Einzeilers) vom Interpreter eingefügt wird, sondern de facto immer als zusätzliche, eigenständige Zeile behandelt wird (natürlich könnte man das im Quellcode des Interpreters nachgucken ;) ) .

Ja, eine Fehlermeldung bzw. ListLines zeigt für das implizite Return zwar die gleiche Zeilennummer an wie die Zeile des Einzeiler-Hotkeys, aber wenn dem impliziten Return stattdessen eine eigene, zusätzliche, neue, Zeilennummer gegeben würde, würden alle anderen Zeilennummern sich als Folge verschieben und nicht mehr mit den Zeilennummern im Editor übereinstimmen und für den Benutzer ganz bestimmt zusätzliche Probleme verursachen.
Wo sollte der Endnutzer diese neue, implizite Zeilennummer in seinem Quellcode finden? Zur Zeit hat er dagegen einen Hinweis, welche Zeile das implizite Return ausgelöst hat.

Wenn man bei diesem Code erst 1 und dann 2 drückt

Code: Select all

x := ""			; 001

1::MsgBox				; 003
2::Listlines			; 004
erhält man dies als ListLines-Ergebnis:

Code: Select all

001: x := ""
003: Return (1.47)
003: MsgBox (0.91)
003: Return (0.38)
004: ListLines
Das zeigt, bei diesem Einzeiler-Hotkey sind sogar zwei implizite Returns auf der gleichen Zeilennummer wie der erste Hotkey angegeben (Zeile 003).

Das erste ( 003: Return (1.47) ) ist das implizite Return vom Ende der auto-execute section, das ja auch irgendwo auftauchen muss und beim ersten Start des Skripts gebraucht wurde (bei weiteren Aufrufen des gleichen 1-Hotkeys erscheint dies dann nicht mehr unter ListLines, weil dann im Vorfeld keine auto-execute section mehr durchlaufen wird).
Das zweite ( 003: Return (0.38) ) ist das implizite Return, das formal den Einzeiler abschließt. Und das steht hier formal sogar für die selbe Zeile wie das msgbox-Kommando verzeichnet, nicht auf der Zeile eines (traditionellen oder irgendeines) If - macht rein syntaxmäßig eigentlich auch keinen Sinn. Zum debuggen schon eher.

Wäre das erste Implizite Return tatsächlich vom Interpreter physikalisch auf der gleichen Zeile (003) wie der Einzeiler-Hotkey eingefügt worden - und noch vor dem Hotkey selbst - dann dürfte der Hotkey selbst ja unerreichbar sein bzw. ungültige Syntax und eine Fehlermeldung erzeugen.
Das zweite hätte auf einer Zeile mit msgbox normalerweise auch keine returnierende Wirkung.

Folgerung:
Implizite Returns werden vom Interpreter bei Ausführung immer als zusätzliche, eigenständige Zeilen eingefügt - erhalten jedoch keine eigene Zeilennummer.

ListLInes und Fehlermeldungen geben stattdessen die Zeilennummer des verursachenden Hotkey-Einzeilers für dieses implizite Return an - vermutlich, damit es bei Analyse besser der auslösenden Zeile zugeordnet werden kann und damit die Zeilennummmern für folgende Zeilen (tatsächlich vorhandene im Quelltext) noch immer aussagekräftig beim debuggen bleiben.

Wie gesagt, eine zweizeilige Konstruktion wie if in einem Einzeiler, wo die nächste Zeile schon feststeht (Return), zu verwenden, hat wenig Nutzwert - aber formal ist es derzeit möglich (bzw. erlaubt), da implizite Returns als eigenständige Zeilen zur Laufzeit eingefügt werden. Es wäre wohl nicht viel verloren, wenn der Interpreter If in Einzeilern grundsätzlich unterbinden würde.
just me
Posts: 6557
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Warum dieser Unterschied?

09 Oct 2019, 08:33

Hallo gregster,

das Verhalten mag ja aus Sicht von AHK formal korrekt sein, aus der Sicht eines Anwenders gehört es aber zumindest in die Kategorie 'Marotten/quirks'.

Code: Select all

g::
IF Mod(Z++,2)
	ToolTip,% Z
Return
zeigt den ToolTip an, wenn die Bedingung erfüllt ist.

Code: Select all

g::IF Mod(Z++,2)
	ToolTip,% Z
Return
zeigt den ToolTip an, wenn die Bedingung nicht erfüllt ist.

Das passiert, weil die If-Anweisung bei erfüllter Bedingung auf eine unsichtbare implizite Return-Anweisung fällt, anderenfalls aber auf die der unsichtbaren Zeile folgende springt. Für mich ist dieses Verhalten nach wie vor unsinnig.
gregster
Posts: 3389
Joined: 30 Sep 2013, 06:48

Re: Warum dieser Unterschied?

09 Oct 2019, 13:08

Aber nach den Doks eignet sich die Einzeiler-Syntax eben auch nur für die Ausführung einer einzigen Zeile - was das sinnvolle Ausführen von zweizeiligen Konstrukten vermutlich implizit ;) auschließt.
Ich wär nicht auf die Idee gekommen, dass man das zweizeilige If in einem Einzeiler verwenden kann - aber der Effekt hier ist tatsächlich sehr unglücklich, wie ich auch selbst feststellen musste (eine Fehlermeldung wär mir lieber gewesen). Fiese Falle :?, keine Frage. Da sind wir uns einig.
just me
Posts: 6557
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Warum dieser Unterschied?

10 Oct 2019, 02:05

OK, ich habe das mal als Bug eingestellt.

Return to “Ich brauche Hilfe”

Who is online

Users browsing this forum: No registered users and 32 guests