Ooker
Ooker

Reputation: 3044

What exactly does `return` do in AutoHotKey?

In a comment chain, I ask:

Hmm, so the return doesn't play like a closing bracket like in other languages?

To which a user answers:

It's maybe easy to think of return as just something that stops the code execution from going further. #IfDirectives don't care about returns, or anything else related to code execution, because they have nothing to do with code execution. They are kind of just markers that enclose different parts of code within them

I have two questions from this:

  1. If return is just something that stops code execution from going further, then how is it different to exit? They are both flow controls playing a role to determine The Top of the Script (the Auto-execute Section). I see that many people having this problem.

  2. If return doesn't play like a closing bracket, then why does it appear in many places one expects a closing bracket? Especially when there is no subroutine involving in, like what is described in the formal definition. Take this example in Hotkeys:

    #n::
    Run Notepad
    return
    

Upvotes: 1

Views: 3928

Answers (3)

kindall
kindall

Reputation: 184280

Return returns from a function (called with funcname(...) syntax) or subroutine (called with Gosub label). Subroutines/functions can call other subroutines/functions and so it's convenient to end them with Return rather than Exit. Exit ends the current thread of execution and won't transfer flow of control back to the caller.

For functions, Return also can return a value.

Return is not analogous to a closing bracket. Closing brackets can occur only at the end of a function and imply a Return but you can also Return anywhere in a function. It is common to return in an If statement to "bail out" of a function early, perhaps if some parameter had an invalid value.

Upvotes: 1

Nor.Z
Nor.Z

Reputation: 1379

Another answer above already gave a good explanation.

So, to me:_

(return vs Exit is like gosub vs goto -- return (literal meaning) vs terminate. )

return completes (ends) the current subroutine, and returns from the current subroutine back to the calling subroutine;

Exit completes (ends) the current subroutine, and terminates (/exits /ends) the current thread (which discards all the previous calling subroutine);

  • where subroutines are inside a thread.
    • (subroutines are just like function calls or label calls (or hotkey label calls); you can visualize this as if method calls (stack frame) in Java (, you can see this when you debug in an IDE))

Quotes:

[]

Return

Returns from a subroutine to which execution had previously jumped via function-call, Gosub, Hotkey activation, GroupActivate, or other means.

https://www.autohotkey.com/docs/commands/Return.htm

[]

Exit

Exits the current thread or (if the script is not persistent) the entire script.

https://www.autohotkey.com/docs/commands/Exit.htm

[]

Gosub

Jumps to the specified label and continues execution until Return is encountered.

https://www.autohotkey.com/docs/commands/Gosub.htm

[]

Goto

Jumps to the specified label and continues execution.

https://www.autohotkey.com/docs/commands/Goto.htm

[]

main difference is gosub comes back, and goto does not.

https://www.autohotkey.com/board/topic/46160-goto-vs-gosub/

[]

A subroutine and a function are essentially the same thing

Difference between subroutine , co-routine , function and thread?

[]

A subroutine is a portion of code which can be called to perform a specific task.

Execution of a subroutine begins at the target of a label and continues until a Return or Exit is encountered.

Since the end of a subroutine depends on flow of control, any label can act as both a Goto target and the beginning of a subroutine.

https://www.autohotkey.com/docs/misc/Labels.htm#subroutines

[]

The current thread is defined as the flow of execution invoked by the most recent event;

examples include hotkeys, SetTimer subroutines, custom menu items, and GUI events.

The current thread can be executing commands within its own subroutine or within other subroutines called by that subroutine.

https://www.autohotkey.com/docs/misc/Threads.htm


(you may try out the following code to see the difference)

^r::
MsgBox, aaa 
gosub, TestLabel
MsgBox, bbb 
goto, TestLabel
MsgBox, ccc 
return

TestLabel:
MsgBox, inside
return
; Exit

Upvotes: 1

0x464e
0x464e

Reputation: 6499

In AHK return is what you'd learn return to be from other programming languages. It's just that control flow, and in general the legacy syntax, in AHK is different from what you might be used to from other languages.

How is return different from exit?

If we're not trying to return a value from a function, and are just interested in the control flow, there is not much difference. But the difference is there.

You could indeed end an hotkey label with exit, and it would be the same as ending it with return.
From the documentation:
"If there is no caller to which to return, Return will do an Exit instead.".
I guess it's just convention to end hotkey labels with return.

So basically said, there is difference between the two, if return isn't about to do an exit.

Well when would this be?
For example:

MsgBox, 1
function()
MsgBox, 3
return ;this does an exit

function()
{
    MsgBox, 2
    return ;this does a return
}

The first return has no caller to which to return to, so it will do an exit.
The second return however does have a caller to return to do, so it will return there, and then execute the 3rd message box.
If we replaced the second return with an exit, the current thread would just be exited and the 3rd message box would never have been shown.

Here's the same exact example with legacy labels:

MsgBox, 1
gosub, label
MsgBox, 3
return ;this does an exit

label:
    MsgBox, 2
return ;this does a return

I'm showing this, because they're very close to hotkey labels, and hotkey labels were something you were wondering a lot about.

In this specific example, if the line MsgBox, 3 didn't exist, replacing the second return with an exit would produce the same end result. But only because code execution is about to end anyway on the first return.


If return doesn't play like a closing bracket, then why does it appear in many places one expects a closing bracket?

In AHK v1, hotkeys and hotstrings work like labels, and labels are legacy. Labels don't care about { }s like modern functions do.
So we need something to stop the code execution. Return does that.

Consider the following example:

c::
    MsgBox, % "Hotkey triggered!"
    gosub, run_chrome
    ;code execution not ended

n::
    MsgBox, % "Hotkey triggered!`nRunning notepad"
    Run, notepad
    ;code execution not ended
    
run_chrome:
    MsgBox, % "Running chrome"
    run, chrome
    WinWait, ahk_exe chrome.exe
    WinMove, ahk_exe chrome.exe, , 500, 500
    ;code execution not ended

show_system_uptime:
    MsgBox, % "System uptime: " A_TickCount " ms"
    ;code execution not ended

We're not ending code execution at any of the labels. Because of this, code execution will bleed into other parts of the code, in this case, into the other labels.
Try running the hotkeys and see how code execution bleeds into the other labels.

Because of this, the code execution needs to be ended somehow.
If using { } was supported by labels, it would indeed be the solution to keep the code execution where it needs to be.
And in fact AHK v2 hotkeys and hotstrings are no longer labels (they're only lookalikes). In v2 using { } is actually the correct way (the script wont even run if you don't use them).
See hotkeys from the AHK v2 documentation.

Upvotes: 3

Related Questions